home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / util / gnu / a2_0b_Emacs_sr.lha / Emacs-19.25 / lisp / ediff.el < prev    next >
Text File  |  1994-05-28  |  145KB  |  3,869 lines

  1. ;;; ediff.el --- a visual interface to diff & patch
  2. ;;; Copyright (C) 1994 Free Software Foundation, Inc.
  3.  
  4. ;; Author: Michael Kifer <kifer@cs.sunysb.edu>
  5. ;; Created: February 2, 1994
  6. ;; Version: 1.52
  7. ;; Keywords: tools
  8.  
  9. ;; This file is part of GNU Emacs.
  10.  
  11. ;; GNU Emacs is free software; you can redistribute it and/or modify
  12. ;; it under the terms of the GNU General Public License as published by
  13. ;; the Free Software Foundation; either version 2, or (at your option)
  14. ;; any later version.
  15.  
  16. ;; GNU Emacs is distributed in the hope that it will be useful,
  17. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. ;; GNU General Public License for more details.
  20.  
  21. ;; You should have received a copy of the GNU General Public License
  22. ;; along with GNU Emacs; see the file COPYING.  If not, write to
  23. ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25.  
  26. ;;; Commentary:
  27. ;;  ----------
  28.  
  29. ;; Never read those diff outputs again!
  30. ;; Apply patch selectively, like a pro!
  31.  
  32. ;; This package provides a convenient way of simultaneous brousing through
  33. ;; the differences between a pair of files or buffers.  The two files being
  34. ;; compared (file-A and file-B) are shown in separate windows (side by
  35. ;; side, one above the another, or in separate frames), and the differences
  36. ;; are highlighted as you step through them.  You can also copy difference
  37. ;; regions from one buffer to another (and recover old differences if you
  38. ;; change your mind).
  39.  
  40. ;; In addition, Ediff can apply a patch to a file and then let you step
  41. ;; though both files, the patched and the original one, simultateously,
  42. ;; difference-by-difference.  You can even apply a patch right out of a
  43. ;; mail buffer, i.e., patches received by mail don't even have to be saved.
  44. ;; Since Ediff lets you copy differences between buffers, you can, in
  45. ;; effect, apply patches selectively (i.e., you can copy a difference
  46. ;; region from file.orig to file, thereby undoing any particular patch that
  47. ;; you don't like).
  48.  
  49. ;; This package builds upon the ideas borrowed from emerge.el.  It is still
  50. ;; using half a dozen of functions defined there. Several other Ediff's
  51. ;; functions are adaptations from emerge.el. Ediff requires, at least, 
  52. ;; Version 5 of emerge.el. This version comes with standard distributions
  53. ;; of Emacs and Lemacs.  Make sure you don't have some stray old copy of
  54. ;; Emerge on your load path.
  55.  
  56. ;; Ediff is complimentary to Emerge.  While Emerge is primarily intended
  57. ;; for merging of files, Ediff is by far superior for browsing through
  58. ;; files compared via diff and for patching files with patch.
  59. ;; Furthermore, Ediff is more convenient even for merging, when one of the
  60. ;; files is a designated output.  This situation arises while patching
  61. ;; files or when comparing an old version of a file with a newer version
  62. ;; (in such cases, it is often desirable to selectively revert some
  63. ;; portions of the new file to its old state).
  64.  
  65. ;; Ediff also supports version control via vc.el (in the standard
  66. ;; distribution of Emacs 19) and rcs.el. The latter is a package written by 
  67. ;; Sebastian Kremer <sk@thp.Uni-Koeln.DE>, which is available in
  68. ;;
  69. ;;         ftp.cs.buffalo.edu:pub/Emacs/rcs.tar.Z
  70. ;;         ftp.uni-koeln.de:/pub/gnu/emacs/rcs.tar.Z
  71. ;;
  72.  
  73.  
  74. ;; Window configuration:
  75. ;; ----------------------
  76.  
  77. ;; By default, Ediff sets things up in one frame, splitting it between a
  78. ;; small control window and the two windows for file-A and file-B.  The
  79. ;; split between these latter windows can be horizontal or vertical, which
  80. ;; can be changed interactively by hitting 's' while the cursor is in the
  81. ;; control window.
  82. ;;
  83. ;; In a multi-frame situation, Ediff would work as follows.  When it starts,
  84. ;; it will place the control window in the frame that was selected at the
  85. ;; time of the invocation.  If file-A or file-B is seen in one of the
  86. ;; frames, Ediff will leave it there.  If a file (A/B) is not visible in any
  87. ;; frame, Ediff will arrange that it will share a frame with the control
  88. ;; window. (If none of the files is visible, then both will share the
  89. ;; control window frame.) The same algorithm works when you hit 'c'
  90. ;; (ediff-recenter), 'p' (ediff-previous-difference), 'n', etc.
  91. ;;
  92. ;; Thus, you can compare files in one frame or in different frames.
  93. ;; The former is done by default, while the latter can be achieved by
  94. ;; arranging files A and B to be seen in different frames.  Ediff
  95. ;; respects these arrangements, automatically adapting itself to 
  96. ;; the multi-frame mode.
  97.  
  98.  
  99. ;; To those who like to go where noone has gone before:
  100.  
  101. ;;  Ediff lets the user run multiple sessions at once, i.e., you can invoke
  102. ;;  Ediff on different functions several times in a row, without exiting
  103. ;;  the previous Ediff sessions. Different sessions may even operate on the
  104. ;;  same pair of files.  So, in principle, it is possible to do, say,
  105. ;;  pairwise comparison of three (or more) different files.  Each session
  106. ;;  would have its own *ediff-control* buffer and all the regarding a
  107. ;;  particular session is local to the associated *ediff-control* buffer.
  108. ;;  You can switch between sessions by suspending one session and then
  109. ;;  switching to another *ediff-control* buffer. (Different such buffers
  110. ;;  are distinguished by a numerical suffix, e.g., *ediff-control*<3>.)
  111. ;;  This, if you would like to compare three files pairwise, you can do
  112. ;;  this by preparing three different frames, each with its own control
  113. ;;  window.  (This would require a very wide screen, and I never claimed
  114. ;;  that such 3-way comparison is very easy to do.)
  115. ;;
  116. ;; If you need to conduct multiple Ediff sessions on the same file, one
  117. ;; thing should be kept in mind: each time you invoke Ediff on a buffer that
  118. ;; already participates in another Ediff session, that buffer should not
  119. ;; have any ASCII Ediff flags in it. (Highlighting with faces is OK.)  If
  120. ;; flags are not removed, difference overlays won't be set correctly
  121. ;; for the second invocation of Ediff.  The simplest way to remove ASCII
  122. ;; flags from an Ediff buffer is to hit `h' and thus switch to highlighting
  123. ;; with faces (unhighlighting on a dumb terminal).
  124.  
  125.  
  126. ;;; Remarks: 
  127. ;;  -------
  128.  
  129. ;;  1. Ediff is heavily dependent on the new features of Emacs 19.
  130. ;;     It won't run under Emacs 18 at all.
  131. ;;  2. If running Lucid Emacs, Ediff requires at least version 19.9.
  132. ;;  3. The function vc-ediff requires the vc.el version that comes with
  133. ;;     Emacs 19.22.
  134.  
  135.  
  136. ;;; Installation and use:
  137. ;;  --------------------
  138.  
  139. ;; You can invoke Ediff interactively using the following functions:
  140. ;;
  141. ;;          ediff-buffers                        - compare buffers
  142. ;;          ediff   (alias for ediff-files)
  143. ;;          ediff-files                        - compare files
  144. ;;          ediff-patch-file                     - patch file then compare
  145. ;;          epatch                               - alias for ediff-patch-file
  146. ;;          ediff-patch-buffer                     - patch buffer then compare
  147. ;;          epatch-buffer                        - alias for ediff-patch-buffer
  148. ;;          vc-ediff                              - compare buffer & version
  149. ;;                                                 using vc.el package
  150. ;;                                                 (Emacs 19.22 and up).
  151. ;;          rcs-ediff                             - same using rcs.el; rcs.el
  152. ;;                                                 is not part of the
  153. ;;                                                 standard Emacs distribution.
  154. ;;
  155. ;; There is also the function ediff-files-remote, which can be invoked only
  156. ;; from within another Emacs Lisp function, i.e., non-interactively.
  157. ;;
  158. ;; To use Ediff, put this in your .emacs file:
  159. ;;
  160. ;;  (autoload 'ediff-buffers "ediff" "Visual interface to diff" t)
  161. ;;  (autoload 'ediff  "ediff"  "Visual interface to diff" t)
  162. ;;  (autoload 'ediff-files "ediff" "Visual interface to diff" t)
  163. ;;  (autoload 'epatch  "ediff"  "Visual interface to patch" t)
  164. ;;  (autoload 'ediff-patch-file "ediff" "Visual interface to patch" t)
  165. ;;  (autoload 'ediff-patch-buffer "ediff" "Visual interface to patch" t)
  166. ;;  (autoload 'epatch-buffer "ediff" "Visual interface to patch" t)
  167. ;;  (autoload 'vc-ediff "ediff"
  168. ;;                      "Interface to diff & version control via vc.el" t) 
  169. ;;  (autoload 'rcs-ediff "ediff"
  170. ;;                       "Interface to diff & version control via rcs.el" t)
  171. ;;
  172. ;;
  173. ;; If you want Ediff to be loaded from the very beginning, you should have
  174. ;;
  175. ;;  (require 'ediff)
  176. ;;
  177. ;; in your .emacs file.  This way it is also easier to figure out changes
  178. ;; to the default Ediff setting, if such changes become necessary --- see
  179. ;; Customization.
  180. ;;
  181.  
  182. ;;; Compilation
  183. ;;  -----------
  184. ;;
  185. ;; When you byte-compile Ediff, you will get some warnings about functions
  186. ;; being undefined.  These can be safely ignored.
  187. ;;
  188. ;;   Important:
  189. ;;   =========
  190. ;;
  191. ;;    If you are using advice.el (directly or indirectly, via one of the
  192. ;;    other packages), Ediff may not compile properly.  In this case, you
  193. ;;    should do:
  194. ;;
  195. ;;          M-x ad-deactivate-all RET
  196. ;;
  197. ;;        M-x byte-compile-file RET ediff.el RET
  198. ;;
  199. ;;        M-x ad-activate-all RET
  200. ;;
  201. ;;    This precaution will not be needed starting with GNU Emacs 19.23 and
  202. ;;    Lucid Emacs 19.10, due to fixing a bug in advice.el.
  203.  
  204. ;;; Customization:
  205. ;;  -------------
  206.  
  207. ;; Hooks:
  208. ;; -----
  209. ;; If you don't like the default setting, you can change it through the
  210. ;; various variables and hooks.  In particular, the following hooks are
  211. ;; available: 
  212.  
  213. ;;        ediff-load-hooks
  214. ;;          ediff-before-setup-windows-hooks
  215. ;;          ediff-startup-hooks
  216. ;;          ediff-select-hooks
  217. ;;          ediff-unselect-hooks
  218. ;;          ediff-suspend-hooks
  219. ;;          ediff-quit-hooks
  220. ;;          ediff-prepare-buffer-hooks
  221.  
  222. ;; The hooks in ediff-load-hooks can be used to change defaults after Ediff
  223. ;; is loaded.
  224. ;; The hooks in ediff-before-setup-windows-hooks, ediff-suspend-hooks, and
  225. ;; ediff-quit-hooks can be used to save and then restore whatever window
  226. ;; configuration you want.  However, make sure you understand what you are
  227. ;; doing.  Many variables that drive Ediff are local to the different
  228. ;; *ediff-control* buffers.  Take a look at ediff-default-suspend-hook and
  229. ;; ediff-default-quit-hook to see what's involved.
  230. ;; The hooks in ediff-prepare-buffer-hooks are executed for each Ediff buffer
  231. ;; (A and B) right after these buffers are arranged.
  232. ;;
  233. ;; Highlighting of difference regions
  234. ;; ----------------------------------
  235. ;; The second group of Ediff variables that could be changed, if you so
  236. ;; wish, is: 
  237. ;;
  238. ;;          ediff-before-flag-eol
  239. ;;          ediff-after-flag-eol
  240. ;;          ediff-before-flag-mol
  241. ;;          ediff-after-flag-mol
  242. ;;
  243. ;;          ediff-current-diff-face-A
  244. ;;          ediff-current-diff-face-B
  245. ;;          ediff-fine-diff-face-A
  246. ;;          ediff-fine-diff-face-B
  247. ;;          ediff-even-diff-face-A
  248. ;;          ediff-even-diff-face-B
  249. ;;          ediff-odd-diff-face-A
  250. ;;          ediff-odd-diff-face-B
  251. ;
  252. ;; The first four are ASCII strings that mark the beginning and the end of
  253. ;; the differences found in file-A and file-B. Ediff uses different flags
  254. ;; to highlight regions that begin/end at the beginning of a line or in a
  255. ;; middle of a line.
  256.  
  257. ;; The rest are the faces used to highlight text on X displays.  On X
  258. ;; displays, Ediff uses ediff-current-diff-face-A and
  259. ;; ediff-current-diff-face-B to highlight the current difference regions.
  260. ;; The faces ediff-fine-diff-face-A and ediff-fine-diff-face-B
  261. ;; are used to show the fine differences between the current differences
  262. ;; regions in buffer A and B.
  263. ;; Other (non-current) difference regions are displayed in alternating
  264. ;; faces: ediff-even/odd-diff-face-A/B.   The odd and the even
  265. ;; faces are actually identical on monochrome displays, because it is
  266. ;; rather poor in what you can do on such a display. So, I chose to use
  267. ;; italics to highlight other differences. Any ideas would be welcome. (In
  268. ;; Lucid Emacs, the faces are different because it supports pixmaps.)
  269. ;; There are two ways to change the default setting for highlighting faces:
  270. ;; either change the variables, as in
  271. ;;
  272. ;; (setq ediff-current-diff-face-A (internal-get-face 'bold-italic))
  273. ;;
  274. ;; (`internal-get-face' should be `get-face' if you are using Lucid Emacs)
  275. ;; or by selectively modifying the defaults:
  276. ;;
  277. ;; (add-hook 'ediff-load-hooks
  278. ;;   (function (lambda () 
  279. ;;                (set-face-foreground ediff-current-diff-face-B "blue")
  280. ;;                (set-face-background ediff-current-diff-face-B "red")
  281. ;;                (make-face-italic ediff-current-diff-face-B))))
  282. ;;
  283. ;; You may also want to take a look at how the above faces are defined in
  284. ;; Ediff. 
  285. ;;
  286. ;; The last group of variables in this group,
  287. ;;
  288. ;;          ediff-want-faces
  289. ;;          ediff-highlight-all-diffs
  290. ;;          ediff-want-default-menus
  291. ;;
  292. ;; indicate whether---on a window system---you want differences to be
  293. ;; marked using ASCII strings (like on a dumb terminal) or using colors and
  294. ;; highlighting. If ediff-want-faces is t, then highlighting with faces is
  295. ;; used. Normally, Ediff highlights all differences, but the selected
  296. ;; difference is highlighted more visibly. You can cycle through various
  297. ;; modes of highlighting by hitting `h'. By default, Ediff starts in the
  298. ;; mode where all difference regions are highlighted. If you prefer to
  299. ;; start in the mode where unselected differences are not highlighted, you
  300. ;; should set ediff-highlight-all-diffs to nil. 
  301. ;; You will still be able to turn on highlighting of all differences by
  302. ;; hitting `h'.
  303. ;; The variable `ediff-want-default-menus', if true, will cause Ediff to
  304. ;; set up a pair of menues in the menu bar, so you can invoke it from there.
  305. ;; If you don't like the look of the default menus, set this variable to
  306. ;; nil and design your own menus.
  307. ;;
  308. ;; If you plan on changing these variables, they must be set
  309. ;; BEFORE ediff.el is loaded. 
  310. ;;
  311. ;; Note: Ediff lets you switch between the two types of highlighting.  That
  312. ;; is you can switch, interactively, from highlighting using faces to
  313. ;; highlighting using ASCII flags, and back.  Of course, toggling has
  314. ;; effect only on a window system.  On a dumb terminal or in an xterm
  315. ;; window, the only available option is highlighting with ASCII flags.
  316. ;;
  317. ;; Refining difference regions
  318. ;; ---------------------------
  319. ;; There are also variables that control the way fine differences are
  320. ;; highlighted. This feature lets the user highlight the exact words that
  321. ;; make the difference regions in buffer A and B different. This process
  322. ;; ignores spaces, tabs, and newlines.
  323. ;;
  324. ;;          ediff-auto-refine
  325. ;;          ediff-auto-refine-limit
  326. ;;
  327. ;; By default, `ediff-auto-refine' is `'on', which means that fine differences
  328. ;; within regions will be highlighted automatically. On a slow system, this
  329. ;; feature may be undesirable. In any case, the user can always toggle
  330. ;; auto-refining on/off/nix by hitting `@'. When auto-refining is off, fine
  331. ;; differences will be shown only for regions for which these differences
  332. ;; have been computed and saved before. If auto-refining is nixed, fine
  333. ;; differences will not be shown at all. Hitting `*' will compute and
  334. ;; display fine differences for the current difference region regardless of
  335. ;; whether auto-refining is on, off, or nixed. 
  336. ;; If auto-refining is on, the variable `ediff-auto-refine-limit' limits
  337. ;; the size of the regions to be auto-refined. This variable guards against
  338. ;; possible slow-down that may be caused by an extraordinary large
  339. ;; difference region. However, the user can always force refining by
  340. ;; hitting `*'.
  341. ;;
  342. ;;          ediff-fine-diff-program
  343. ;;          ediff-fine-diff-options
  344. ;;          ediff-wordify-function
  345. ;;
  346. ;; These variables let the user control how fine differences are computed.
  347. ;; `ediff-fine-diff-program' is diff, by default. However, you can use
  348. ;; any function as long as it produces output consistent with diff.
  349. ;; `ediff-wordify-function' is a lisp function that determines how the
  350. ;; current difference region is split into words. (Fine diferences are
  351. ;; computed by first splitting the current difference region into words and
  352. ;; then passing this along to `ediff-fine-diff-program'. For the default
  353. ;; wordify function, `ediff-wordify', a word is a string consisting of
  354. ;; letters, `-', or `_', or a string consisting of symbols that are neither
  355. ;; space, nor a letter.)
  356. ;;
  357. ;; Patch and diff programs
  358. ;; -----------------------
  359. ;; The next group of variables determines the programs to be used for
  360. ;; applying patches and for computing the main difference regions (not the
  361. ;; fine difference regions):
  362. ;;
  363. ;;          ediff-patch-program
  364. ;;          ediff-patch-options
  365. ;;          ediff-diff-program
  366. ;;          ediff-diff-options
  367. ;;
  368. ;; These specify the functions that produce differences and do patching.
  369. ;; The *-options variables specify which options to pass to these programs.
  370. ;; It is unlikely that you would want to change these.  One possible
  371. ;; exception is when you may want to generate differences with context
  372. ;; lines in order to send a patch file through email.  Then, you might want
  373. ;; to set ediff-diff-options to '-c'. Sometimes, you may also want to tell
  374. ;; diff to ignore spaces and such. Use the option '-w' for that. Diff
  375. ;; has several other useful options (type 'man diff' to find out).
  376. ;;
  377. ;; The output from diff is found in *ediff-diff* buffer.  However, this
  378. ;; makes sense only if you also intend to use Ediff to browse through the
  379. ;; diff'ed files before sending the patch.  This is because diff.el is much
  380. ;; faster in yielding the output of diff  (Ediff is a big gun, if used
  381. ;; for this simple purpose).
  382. ;;
  383. ;; Miscellaneous
  384. ;; -------------
  385. ;; The last set of variables that can be modified is
  386. ;;
  387. ;;          ediff-split-window-function
  388. ;;          ediff-use-last-dir
  389. ;;          ediff-no-help-in-control-buffer
  390. ;;
  391. ;; ediff-split-window-function controls the way you want the window be
  392. ;; split between file-A and file-B.  It defaults to vertical split, but you
  393. ;; can set it to 'split-window-horizontally, if you want.  Ediff lets you
  394. ;; toggle the way windows are split, so you can try different settings
  395. ;; interactively.  Note: if file-A and file-B are in different frames,
  396. ;; windows are not split, regardless of the value
  397. ;; ediff-split-window-function.  Instead, other windows on these frames are
  398. ;; deleted and Ediff starts displaying file-A and file-B using these two
  399. ;; frames, one file per frame.  You can then switch to one-frame mode
  400. ;; simply by hiding the file-A/B buffer that is displayed on a frame other
  401. ;; than the control-window frame.
  402. ;;
  403. ;; Note that if Ediff sees that the two buffers it compares are residing in
  404. ;; separate frames, it assumes that the user wants them to be so displayed
  405. ;; and stops splitting windows.  Instead, it will arrange each buffer to
  406. ;; occupy its own frame (possibly shared with Ediff's help window).
  407. ;;
  408. ;; The variable ediff-use-last-dir controls the way Ediff presents the
  409. ;; default directory when it prompts the user for files to compare.  If nil,
  410. ;; Ediff will use the default directory of the current buffer when it
  411. ;; prompts the user for file names.  Otherwise, it will use the
  412. ;; directories it had previously used for file-A and file-B. 
  413. ;;
  414. ;; The ediff-no-help-in-control-buffer, if set to t, makes C-h behave like
  415. ;; the DEL key, i.e., it will move you back to the previous difference
  416. ;; rather than invoking help.  This is useful when, in an xterm window or on
  417. ;; a dumb terminal, the Backspace key is bound to C-h and is positioned
  418. ;; more conveniently than the DEL key.
  419.  
  420.  
  421. ;;; Commands
  422. ;;  --------
  423.  
  424. ;; All Ediff commands are displayed in a help window, unless you hit '?' to
  425. ;; shrink it to just one line.  You can redisplay the help window by hitting
  426. ;; '?' again.
  427. ;;
  428. ;; Many Ediff commands take numeric prefix arguments.  For instance, if you
  429. ;; hit a number, N, and then 'j' (ediff-jump-to-difference), Ediff will
  430. ;; take you to Nth difference.  Hitting a number, N, and then 'ab'
  431. ;; (ediff-diff-to-diff) will copy Nth difference from buffer A to buffer B.
  432. ;; Hitting 'ba' does copying in the other direction.
  433. ;; Likewise, a number, N, followed by 'ra' will restore the Nth difference
  434. ;; region in buffer A (if it was previously saved as a result of copying
  435. ;; from B to A). 
  436. ;;
  437. ;; Without the prefix argument, all commands operate on the current
  438. ;; difference region.
  439. ;;
  440. ;; The total number of differences and the current difference number are
  441. ;; always displayed in the mode line of the control window. 
  442.  
  443. ;;; Display Modes
  444. ;;  -------------
  445.  
  446. ;; Ediff can display files in one frame, stacked side-by-side or one on top
  447. ;; of another; or it can display the files in different frames.  When you
  448. ;; start Ediff, it assumes a 1-frame mode.  You can toggle the side-by-side
  449. ;; and one-on-top-of-another displays by simply hitting 's'.
  450. ;;
  451. ;; Ediff switches to the multi-frame mode when:
  452. ;;
  453. ;;  1. file-A and file-B are in different frames (you have to put them into
  454. ;;     different frames manually); or
  455. ;;  2. *ediff-control* buffer is visible in one frame and one other file (A
  456. ;;     or B) is visible in another frame.  If, say, fileA is visible in a
  457. ;;     different frame than *ediff-control*, fileB doesn't have to be
  458. ;;     visible.  If it is, Ediff will continue displaying fileB in the frame
  459. ;;     where it was visible before.  If it isn't then Ediff will arrange for
  460. ;;     fileB to share a frame with *ediff-control*.
  461. ;;
  462. ;;  If all three buffers are in separate frames, Ediff will switch to a
  463. ;;  3-frame mode.  If Ediff buffers are currently visible only in two
  464. ;;  frames, Ediff will work in a 2-frame mode.  In this mode, one of the
  465. ;;  frames will be shared by *ediff-control* and file-A or file-B
  466. ;;  (whichever is appropriate).
  467.  
  468.  
  469. ;;; Bugs:
  470. ;;  ----
  471.  
  472. ;;  1. The undo command doesn't restore deleted regions well. That is, if
  473. ;;  you delete all characters in a difference region and then invoke
  474. ;;  `undo', the reinserted text will most likely be reinserted outside of
  475. ;;  what Ediff thinks is the current difference region. (This problem
  476. ;;  doesn't seem to exist with Lucid Emacs.)
  477. ;;
  478. ;;  If at any point you feel that difference regions are no longer correct,
  479. ;;  you can hit '!' to recompute the differences.
  480.  
  481. ;;  2. Emacs 19.xx, where xx < 23, has several bugs related to overlays and
  482. ;;  faces. Somethimes, these may cause highlighting of the refinements or
  483. ;;  of the unselected differences to disappear. Hitting `!' will bring them
  484. ;;  back.  In version 19.23, these problems no longer occur.
  485.  
  486. ;;  3. On a monochrome display, the repertoire of faces with which to
  487. ;;  highlight fine differences is limited. By default, Ediff is using
  488. ;;  underlining. However, if the region is already underlied by some other
  489. ;;  overlays, there is no simple way to temporarily remove that residual
  490. ;;  underlining. This problem occurs when a buffer is highlighted with
  491. ;;  hilit19.el or font-lock.el packages. If this residual highlighting gets
  492. ;;  in the way, you can do the following. Both font-lock.el and hilit19.el
  493. ;;  provide commands for unhighlighting buffers. You can either place these
  494. ;;  commands in `ediff-prepare-buffer-hooks' (which will unhighlight every
  495. ;;  buffer used by Ediff) or you can execute them interactively, at any time
  496. ;;  and on any buffer.
  497.  
  498. ;;  4. In Lucid Emacs (statically linked with Motif libraries), emerge.el
  499. ;;  and hence ediff.el won't start, unless you set (setq scrollbar-width 0).
  500. ;;  This is a Motif-related bug, I was told.
  501.  
  502.  
  503. ;;; Change Log:
  504. ;;  ----------
  505.  
  506. ;; Thu Feb  3, 1994 
  507.  
  508. ;;     Added ediff-read-file-name, which is a stub that takes care of Lemacs
  509. ;;     versions of Emerge. (Thanks to Alastair Burt <burt@dfki.uni-kl.de>.)
  510. ;;
  511. ;;     Fixed a bug in ediff-setup-windows that caused control window to
  512. ;;     appear in a wrong place when split-window-keep-point is nil
  513. ;;     (Thanks to Kevin Broadey <KevinB@bartley.demon.co.uk>.)
  514. ;;
  515. ;;     Added mechanism for using faces instead of before/after flags.  This
  516. ;;     looks much better on an X display, especially on a color one.
  517. ;;     (Thanks to Boris Goldowsky <boris@cs.rochester.edu> for the code
  518. ;;     that led to ediff-highlight-diff.
  519. ;;     Also, thanks to Kevin Esler <esler@ch.hp.com> for suggestions
  520. ;;     regarding highlighting differences on X displays.)
  521. ;;
  522. ;;     Added functions to apply patches.
  523. ;;     (Thanks to Kevin Broadey <KevinB@bartley.demon.co.uk> for this
  524. ;;     suggestion.)
  525.  
  526. ;; Fri Feb  4, 1994 
  527.  
  528. ;;     Added mechanism for toggling vertical/horizontal window split.
  529. ;;     (Inspired by a suggestion from Allan Gottlieb
  530. ;;     <gottlieb@allan.ultra.nyu.edu> -- thanks.)
  531. ;;
  532. ;;     Added mechanism for toggling between highlighting using faces and
  533. ;;     highlighting using ASCII flags.
  534. ;;
  535. ;;     Fixed a problem with undo.  Now, Ediff has smartened up and doesn't
  536. ;;     keep undo info on ASCII flags inserted in buffer-A and buffer-B.
  537. ;;     So, if you edit the files while browsing through them, undo behaves
  538. ;;     as you would expect, i.e., faces/flags don't get in the way.
  539.  
  540. ;; Sun Feb  6, 1994 
  541.  
  542. ;;     Added horizontal scrolling.  Added ediff-position-region to ensure
  543. ;;     that difference regions in buffer-A and buffer-B are aligned with
  544. ;;     each other.  Disabled ediff-toggle-split when buffers are displayed
  545. ;;     in different frames.
  546.  
  547. ;; Mon Feb  7, 1994
  548.  
  549. ;;     Added toggle-window help (Suggested by Boris Goldowsky
  550. ;;     <boris@cs.rochester.edu>.)
  551. ;;     Added functions to copy differences from one buffer to another and to
  552. ;;     recover old differences.
  553. ;;     Added prefix arguments to ediff-next-difference and
  554. ;;     ediff-previous-difference.
  555.  
  556. ;; Tue Feb  8, 1994
  557.  
  558. ;;     Replaced text properties with overlays.  Fixed ediff-setup-windows.
  559. ;;     Added ediff-save-buffer to local-write-file-hooks to prevent user
  560. ;;     from saving corrupted states. (Thanks to <boris@cs.rochester.edu>
  561. ;;     for suggestion.)  Instead, Ediff now has a pair of functions for
  562. ;;     safe saving of buffers. 
  563. ;;     Changed ediff-read-file-name to be more intuitive on ediff-files.
  564. ;;     Added ediff-prepare-buffer-hooks. (Thanks to Kevin Esler
  565. ;;     <esler@ch.hp.com> for the idea.)
  566.  
  567. ;; Wed Feb  9, 1994
  568.  
  569. ;;     Cleanups in ediff-patch-file.  Protected ediff-copy-diff against
  570. ;;     a bug that Emacs has in kill-region.
  571.  
  572. ;; Thu Feb 10, 1994
  573.  
  574. ;;     Added support for Lemacs. (Thanks to Alastair Burt
  575. ;;     <burt@dfki.uni-kl.de> for coercing Ediff into working under Lemacs.)
  576. ;;     Added ediff-kill-buffer-carefully and other suggestions by Boris
  577. ;;     Goldowsky <boris@cs.rochester.edu>.
  578. ;;     Refined the protection against interference with highlighting caused
  579. ;;     by Hilit19.  Added the variable ediff-third-party-highlighting.
  580. ;;     Added mechanisn for unhighlighting regions highlighted with Hilit19
  581. ;;     before hightlighting them with Ediff's overlays. (And for
  582. ;;     rehighlighting them with Hilit19, when the current difference moves on.)
  583.  
  584. ;; Sun Feb 13, 1994
  585.  
  586. ;;     Added ediff-place-flags-in-buffer and ediff-remote-exit, which are
  587. ;;     modifications of Emerge's similar functions.  The difference is that
  588. ;;     in Ediff they make ediff-before-flag and ediff-after-flag into
  589. ;;     read-only regions, so the user can't change them by mistake.
  590. ;;
  591. ;;     Adopted a suggestion by Boris Goldowsky <boris@cs.rochester.edu>
  592. ;;     that led to a more elegant treatment of faces.
  593. ;;
  594. ;;     Added protection against interference with Font-Lock highlighting
  595. ;;     similar to that of Hilit19's protection.
  596.  
  597. ;; Tue Feb 15, 1994
  598.  
  599. ;;     Deleted spurious (auto-save-mode 1) in ediff-control-buffer, which
  600. ;;     was causing this buffer to be auto-saved for no good reason.
  601. ;;     Added read-only protection to ediff-before/after-flags in Lemacs.
  602. ;;     (Thanks to Alastair Burt <burt@dfki.uni-kl.de> for help in testing.)
  603.  
  604. ;; Wed Feb 16, 1994
  605.  
  606. ;;     Further fixes in the Lemacs part.  Changed highlighted region in
  607. ;;     ediff-highlight-diff so that an extra character will be highlighted
  608. ;;     only if a difference is empty (thereby allowing the user to see where an
  609. ;;     insertion or a deletion has taken place).
  610. ;;
  611. ;;     Simplified interaction with other highlighting packages by giving
  612. ;;     Ediff overlays the highest priority. (Taking a cue from
  613. ;;     ediff-highlight-diff-lemacs written by Alastair Burt
  614. ;;     <burt@dfki.uni-kl.de>.) Zapped ediff-third-party-highlighting
  615. ;;     variable and hooks that were previously used to
  616. ;;     unhighlight/rehighlight buffers when hilit19/font-lock are on.
  617.  
  618. ;; Fri Feb 18, 1994
  619.  
  620. ;;     Added a bit more sophistication to ediff-read-file-name.  Now,
  621. ;;     ediff-files remembers both, the file-A and the file-B directories.
  622. ;;     They are offered as defaults when ediff-use-last-dir is set to t.
  623.  
  624. ;; Fri Feb 22, 1994
  625.  
  626. ;;     Added ediff-before-change-guard to remove ASCII highlighting when
  627. ;;     the user attempts to change buffer-A/B.  This is needed because
  628. ;;     otherwise the undo info may become screwed up in those buffers.
  629. ;;     Hitting 'h' (ediff-toggle-hilit) on a dumb terminal will toggle
  630. ;;     between ASCII highlighting and no highlighting.
  631.  
  632. ;; Fri Feb 24, 1994
  633.  
  634. ;;     Fixed problems with multiple Ediff sessions running simultaneously.
  635.  
  636. ;; Tue Mar 1, 1994
  637.  
  638. ;;     Added vc-ediff, the Ediff interface to vc.el. (Thanks to Eric
  639. ;;     Freudenthal <freudent@jan.ultra.nyu.edu> for contributing this
  640. ;;     function.) 
  641.  
  642. ;; Sun Mar 6, 1994
  643.  
  644. ;;     Added rcs-ediff, an Ediff interface to RCS via rcs.el. (Thanks to
  645. ;;     Alastair Burt  <burt@dfki.uni-kl.de>.)
  646. ;;     Some minor improvements.
  647.  
  648. ;; Tue March 15, 1994
  649.  
  650. ;;     Fixed a buglet in defining ediff-current-diff-face-A/B.
  651. ;;     (Thanks to Job Ganzevoort  <Job.Ganzevoort@cwi.nl>.) 
  652.  
  653. ;; Tue March 22, 1994
  654.  
  655. ;;     Fixed a bug with ediffing narrowed buffers, reported by Kevin
  656. ;;     Broadey <KevinB@bartley.demon.co.uk>.
  657. ;;     Made Ediff to work with files that have incomplete last line.
  658. ;;     Made Ediff execute diff and patch using Bourne Shell, which
  659. ;;     should eliminate problems with $prompt that some people had.
  660.  
  661. ;; Thu March 24, 1994
  662.  
  663. ;;     Achieved quadratic speedup in the size of the file by replacing the
  664. ;;     slow goto-line by forward-line.  Ediff is now *much* faster than
  665. ;;     Emerge on large files.  Converted demarkation of difference regions
  666. ;;     from markers to overlays.  This will later allow us to highlight all
  667. ;;     diffs, not just the current one.
  668.  
  669. ;; Wed March 30, 1994
  670.  
  671. ;;     Under X, Ediff now highlights all differences in dim colors and the
  672. ;;     current difference in bright colors. Improved Lucid Emacs support.
  673.  
  674. ;; Thu March 31, 1994
  675.  
  676. ;;     Changed toggle hilit to cycle through 3 states: highlighting all
  677. ;;     diffs, highlighting only the current diff, and highlighting using
  678. ;;     ASCII flags.
  679. ;;     Added support for difference regions that are not full lines.
  680.  
  681. ;; Fri April 1, 1994
  682.  
  683. ;;     Fixed bugs related to writing buffers A and B.
  684. ;;     Added commands 'ga', 'gb' to jump directly to the closest diff in
  685. ;;     buffer A and B, respectively.
  686.  
  687. ;; Fri April 11, 1994
  688.  
  689. ;;     Added `ediff-recompute-diffs', a function that lets the user recompute
  690. ;;     difference regions after extensive editing done to buffers A and B
  691. ;;     (bound to `!').
  692.  
  693. ;; Wed April 13, 1994
  694.  
  695. ;;     Added the new feature: refining the current difference region.
  696. ;;     This would highlight the precise differences between the regions in
  697. ;;     buffer A and B. (A way to implement this was suggested by Boris
  698. ;;     Goldowsky <boris@cs.rochester.edu>.)
  699. ;;
  700. ;;     Fixed Ediff to be immune to several different versions of rcs.el
  701. ;;     that are currently in distribution.
  702.  
  703. ;; Thu April 14, 1994
  704.  
  705. ;;     Ediff now respects X resources for the faces it uses. It no longer
  706. ;;     barks when the colormap has no colors it is using; or when face
  707. ;;     fonts can't be italicized, etc.
  708.  
  709. ;; Fri April 15, 1994
  710.  
  711. ;;     Changed `ediff-setup-windows' to minimize the need to delete and
  712. ;;     create windows. Now jumps faster from diff to diff.
  713.  
  714. ;; Sat April 16, 1994
  715.  
  716. ;;     Added Ediff to the File menu on the menu bar (FSF's version).
  717.  
  718. ;; Mon April 18, 1994
  719.  
  720. ;;     Fixed to work with OS/2's PM-Emacs.
  721.  
  722. ;; Thu April 21, 1994
  723.  
  724. ;;     Lemacs' menus added (thanks to Alastair Burt for the help).
  725.  
  726. ;; Wed April 28, 1994
  727.  
  728. ;;     Fixed ediff-leave-window-config (thanks to Norbert Kiesel 
  729. ;;     <norbert@i3.informatik.rwth-aachen.de>), ediff-shell and
  730. ;;     ediff-protect-metachars (thanks to Richard Stanton
  731. ;;     <stanton@haas.berkeley.edu>). Made access to difference
  732. ;;     overlays structure-independent, making it less bug-prone.
  733. ;;     Patched ediff-read-file-name to work more intuitively with directory
  734. ;;     names (thanks to Kevin Broadey <KevinB@bartley.demon.co.uk>).
  735.  
  736. ;; Mon May 2, 1994
  737.  
  738. ;;     Added `ediff-frame-has-menubar' to guard against the possibility that
  739. ;;     the current frame has no menu bar.
  740.  
  741. ;; Fri May 6, 1994
  742.  
  743. ;;     Fixed buglet in vc-ediff (thanks to Ray Nickson <nickson@cs.uq.oz.au>).
  744.  
  745.  
  746. ;;; Acknowledgements:
  747.  
  748. ;; Special thanks to Alastair Burt <burt@dfki.uni-kl.de>, Kevin Esler
  749. ;; <esler@ch.hp.com>, Kevin Broadey <KevinB@bartley.demon.co.uk>, 
  750. ;; Eric Freudenthal <freudent@jan.ultra.nyu.edu>, Job Ganzevoort
  751. ;; <Job.Ganzevoort@cwi.nl>, Boris Goldowsky <boris@cs.rochester.edu>,
  752. ;; Allan Gottlieb <gottlieb@allan.ultra.nyu.edu>, Xiaoli Huang
  753. ;; <hxl@epic.com>, irvine@lks.csi.com, jaffe@chipmunk.cita.utoronto.ca,
  754. ;; David Karr, <dkarr@nmo.gtegsc.com>, Norbert Kiesel 
  755. ;; <norbert@i3.informatik.rwth-aachen.de>, Heinz Knutzen
  756. ;; <hk@informatik.uni-kiel.d400.de>, Martin Maechler
  757. ;; <maechler@stat.math.ethz.ch>, Richard Mlynarik <mly@adoc.xerox.com>,
  758. ;; Ray Nickson <nickson@cs.uq.oz.au>, Andy Scott <ascott@pcocd2.intel.com>,
  759. ;; Richard Stanton <stanton@haas.berkeley.edu>, for contributing ideas,
  760. ;; patches and bug reports. 
  761. ;;
  762. ;; Thanks also to many others who felt obliged to drop a thanks note.
  763.  
  764.  
  765.  
  766. ;;; Code:
  767.  
  768. (require 'emerge) ;; Ediff uses some functions defined in emerge.el
  769.  
  770.  
  771. ;;; Macros
  772. (defmacro ediff-if-lucid ()
  773.   (` (string-match "Lucid" emacs-version)))
  774.  
  775. (defmacro ediff-odd-p (arg)
  776.   (` (eq (logand (, arg) 1) 1)))
  777.  
  778. (defmacro ediff-buffer-live-p (buf)
  779.   (` (and (, buf) (get-buffer (, buf)) (buffer-name (get-buffer (, buf))))))
  780.  
  781. (defmacro ediff-get-buffer (arg)
  782.   (` (cond ((eq (, arg) 'A) ediff-A-buffer)
  783.        ((eq (, arg) 'B) ediff-B-buffer)
  784.        )
  785.   ))
  786.        
  787. (defmacro ediff-char-to-buftype (arg)
  788.   (` (cond ((eq (, arg) ?a) 'A)
  789.        ((eq (, arg) ?b) 'B)
  790.        )
  791.   ))
  792.   
  793. (defmacro ediff-get-difference (n)
  794.   (` (aref ediff-difference-vector (, n))))
  795.   
  796. (defmacro ediff-get-diff-overlay-from-vector (vec buf-type)
  797.   (` (aref (, vec)
  798.        (cond ((eq (, buf-type) 'A) 0)
  799.          ((eq (, buf-type) 'B) 1)
  800.          )
  801.        )))
  802.   
  803. (defmacro ediff-get-diff-overlay (n buf-type)  
  804.   (` (ediff-get-diff-overlay-from-vector
  805.       (ediff-get-difference (, n))
  806.       (, buf-type))))
  807.  
  808. (defmacro ediff-get-fine-diff-vector-from-vec (current-diff-vec)
  809.   (` (aref (, current-diff-vec) 2)))
  810.       
  811. (defmacro ediff-set-fine-diff-vector (n fine-vec)
  812.   (` (aset (ediff-get-difference (, n)) 2 (, fine-vec))))
  813.   
  814. (defmacro ediff-get-fine-diff-vector (n)
  815.   (` (ediff-get-fine-diff-vector-from-vec (ediff-get-difference (, n)))))
  816.   
  817. (defmacro ediff-frame-has-menubar ()
  818.   (if (ediff-if-lucid)
  819.       current-menubar
  820.     (< 0 (cdr (assq 'menu-bar-lines (frame-parameters (selected-frame)))))
  821.     ))  
  822.  
  823.  
  824. ;;; Functions
  825.  
  826. (defun ediff-mode ()
  827.   "Ediff mode is used by the Ediff file-difference package.
  828. It is entered only through one of the following commands:
  829.     `ediff'
  830.     `ediff-files'
  831.     `ediff-buffers'
  832.     `epatch'
  833.     `ediff-patch-file'
  834.     `ediff-patch-buffer'
  835.     `epatch-buffer'
  836.     `vc-ediff'
  837.     `rcs-ediff'
  838. or through a non-interactive Emacs Lisp function    
  839.     `ediff-files-remote'
  840.  
  841. Commands:
  842. \\{ediff-mode-map}"
  843.   (interactive)
  844.   (kill-all-local-variables)
  845.   (setq major-mode 'ediff-mode)
  846.   (setq mode-name "Ediff"))
  847.  
  848. (defvar ediff-version "1.52"
  849.   "The current version of Ediff.")
  850.  
  851. (defun ediff-version ()
  852.   "Return string describing the version of Ediff.
  853. When called interactively, displays the version."
  854.   (interactive)
  855.   (if (interactive-p)
  856.       (message "Ediff version %s" (ediff-version))
  857.     ediff-version))
  858.  
  859.  
  860. ;; Hook variables
  861.  
  862. (defvar ediff-before-setup-windows-hooks nil
  863.   "*Hooks to run before Ediff sets its own window config. 
  864. This can be used to save the previous window config, which can be restored
  865. on ediff-quit or ediff-suspend.") 
  866. (defvar ediff-startup-hooks nil
  867.   "*Hooks to run in the control buffer after Ediff has been set up.")
  868. (defvar ediff-select-hooks nil
  869.   "*Hooks to run after a difference has been selected.")
  870. (defvar ediff-unselect-hooks nil
  871.   "*Hooks to run after a difference has been unselected.")
  872. (defvar ediff-prepare-buffer-hooks  nil
  873.   "*Hooks called after buffers A and B are set up.")
  874. (defvar ediff-load-hooks nil
  875.   "*Hook run after Ediff is loaded.  Can be used to change defaults.")
  876.  
  877. (defvar ediff-suspend-hooks (list 'ediff-default-suspend-hook)
  878.   "*Hooks to run in the Ediff control buffer when Ediff is suspended.")
  879. (defvar ediff-quit-hooks (list 'ediff-default-quit-hook)
  880.   "*Hooks to run in the Ediff control buffer after finishing Ediff.") 
  881.  
  882. (make-variable-buffer-local 'local-write-file-hooks)
  883. (make-variable-buffer-local 'before-change-function)
  884.  
  885. ;; Help messages
  886.  
  887. (defconst ediff-help-message-long
  888.   "p,DEL - prev diff      v/V - scroll up/dn    * - refine diff  ! - recomp diffs
  889. n,SPC - next diff      </> - scroll lt/rt   ab - diff A to B  l - line numbers
  890.     j - jump to diff     s - toggle split   ba - diff B to A  f - file names
  891. ga/gb - goto pt in A/B   h - toggle hilit   ra - restore A    z - suspend Ediff
  892.     c - recenter         @ - toggle refine  rb - restore B    q - quit Ediff
  893. wa/wb - save buf A/B   A/B - toggle read-only in buffers A/B  ? - toggle help")
  894.               
  895. (defconst ediff-help-message-short
  896.   "                          ? - toggle help window")              
  897.  
  898. (defvar ediff-help-message ediff-help-message-long
  899.   "*The actual help message.")
  900.  
  901. ;; diff stuff.
  902. (defvar ediff-diff-program "diff"
  903.   "*Name of the program that compares two files.")
  904. (defvar ediff-diff-options ""  
  905.   "*Options to pass to `ediff-diff-program'.")
  906.   
  907. ;; Find diff stuff.
  908. (defvar ediff-wordify-function 'ediff-wordify
  909.   "*Function to call to split current diff region into separate words.")
  910.  
  911. (defvar ediff-fine-diff-program "diff"
  912.   "*Name of the program that compares the current diff regions for fine differences.
  913.   
  914. This program should produce output in the format of diff. One could
  915. possibly use `spiff' here if appropriate options are set.")
  916.  
  917. (defvar ediff-fine-diff-options ""  
  918.   "*Options to pass to `ediff-fine-diff-program'.")
  919.   
  920. (defvar ediff-whitespace " \n\t\j"
  921.   "*White space. Used to split strings into words.")
  922.  
  923. (defvar ediff-word-1 "a-zA-Z---_`'.?!:"
  924.   "*Characters constituting type 1 words.
  925.   
  926. Ediff is using a very simple schema for splitting text into words, which is
  927. used to determine fine differences between regions. There are two types of
  928. words. One consists entirely out of characters in `ediff-word-1'  and
  929. another out of characters matching `ediff-word-1'.")
  930.  
  931. (defvar ediff-word-2 "^a-zA-Z---_`'.?!: \t\n\j"
  932.   "*Characters matching this regexp constitute words of type 2.
  933. See `ediff-word-1' for more details.")  
  934.   
  935.  
  936. ;; Support for patches 
  937.  
  938. (defvar ediff-patch-program "patch"
  939.   "*Name of the program that applies patches.")
  940. (defvar ediff-patch-options ""
  941.   "*Options to pass to ediff-patch-program.")
  942.   
  943. (defvar ediff-shell (cond ((eq system-type 'emx) "cmd") ;; OS/2
  944.               (t  "sh")) ;; unix
  945.   "*The shell used to run diff and patch.  If user's .profile or
  946. .cshrc files are set up correctly, any shell will do.  However, some people
  947. set $prompt or other things incorrectly, which leads to undesirable output
  948. messages.  These may cause Ediff to fail.  In such a case, set ediff-shell
  949. to a shell that you are not using or, better, fix your shell's startup file.")
  950.   
  951. (defvar ediff-diff-ok-lines-regexp  
  952.   "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\|Warning:\\)"
  953.   "*Regexp that matches normal output lines from `ediff-diff-program'.
  954. This is mostly lifted from Emerge, except that Ediff also considers the
  955. 'Missing newline' message to be 'normal output.'
  956. Lines that do not match are assumed to be error messages.")
  957.  
  958. (defvar ediff-fine-diff-ok-lines-regexp  
  959.   "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\|Warning:\\)"
  960.   "*Regexp that matches normal output lines from `ediff-fine-diff-program'.
  961. This is mostly lifted from Emerge, except that Ediff also considers the
  962. 'Missing newline' message to be 'normal output.'
  963. Lines that do not match are assumed to be error messages.")
  964.  
  965. (defvar ediff-match-diff-line (let ((x "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)"))
  966.                 (concat "^" x "\\([acd]\\)" x "$"))
  967.   "*Pattern to match lines produced by diff that describe differences.")
  968.   
  969. (defvar ediff-patch-buf nil
  970.   "The buffer of the patch file.")
  971. (defvar ediff-patch-diagnostics nil
  972.   "The buffer where patch would display its diagnostics.")
  973.   
  974.  
  975. ;; Copying diffs betw buffers.    
  976.  
  977. (emerge-defvar-local ediff-killed-diffs-alist nil
  978.   "A list of killed diffs. 
  979. A diff is saved here if it is replaced by a diff
  980. from another buffer.  This alist has the form:
  981. \((num (A . diff) (B . diff)) ...),
  982. where A or B parts may be missing.")
  983.  
  984.  
  985. ;; Highlighting
  986. (defvar ediff-before-flag-bol
  987.   ;"vvvvvvvvvvvvvvvv---- ediff ----vvvvvvvvvvvvvvv\n"
  988.   ">>--->>>\n"
  989.   "*Flag placed above the highlighted block of differences. 
  990. Must end with newline.  Must be set before Ediff is loaded.")
  991. (defvar ediff-after-flag-bol
  992.   ;"^^^^^^^^^^^^^^^^---- ediff ----^^^^^^^^^^^^^^^\n"
  993.   "<<<---<<\n"
  994.   "*Flag placed below the highlighted block of differences.
  995. Must end with newline.  Must be set before Ediff is loaded.")
  996.  
  997. (defvar ediff-before-flag-mol ">>--->>>"
  998.   "*Like ediff-before-flag, used when a difference starts in mid-line.")
  999. (defvar ediff-after-flag-mol "<<<---<<"
  1000.   "*Like ediff-after-flag, used when a difference starts in mid-line.")
  1001.  
  1002. (emerge-defvar-local ediff-before-flag-A nil
  1003.   "This is the actual ASCII before-flag in effect in buffer A.
  1004. It is either `ediff-before-flag-mol' or `ediff-before-flag-bol' depending
  1005. on whether the selected difference region starts in the middle of a line 
  1006. or at the beginning of a line.")
  1007. (emerge-defvar-local ediff-after-flag-A nil
  1008.   "This is the actual ASCII after-flag in effect in buffer A.
  1009. It is either `ediff-before-flag-mol' or `ediff-before-flag-bol' depending
  1010. on whether the selected difference region starts in the middle of a line 
  1011. or at the beginning of a line.")
  1012. (emerge-defvar-local ediff-before-flag-B nil
  1013.   "This is the actual ASCII before-flag in effect in buffer B.
  1014. It is either `ediff-before-flag-mol' or `ediff-before-flag-bol' depending
  1015. on whether the selected difference region starts in the middle of a line 
  1016. or at the beginning of a line.")
  1017. (emerge-defvar-local ediff-after-flag-B nil
  1018.   "This is the actual ASCII after-flag in effect in buffer B.
  1019. It is either `ediff-before-flag-mol' or `ediff-before-flag-bol' depending
  1020. on whether the selected difference region starts in the middle of a line 
  1021. or at the beginning of a line.")
  1022.  
  1023.   
  1024. (emerge-defvar-local ediff-want-faces t
  1025.   "If t, differences are highlighted using faces on a window system.
  1026. If nil, they are highlighted using ASCII flags, ediff-before-flag
  1027. and ediff-after-flag.  On a non-window system, differences are always
  1028. highlighted using ASCII flags.
  1029.  
  1030. This variable can be set either in .emacs or toggled interactively, using
  1031. ediff-toggle-hilit.") 
  1032.  
  1033. (emerge-defvar-local ediff-want-default-menus t
  1034.   "If t, Ediff will set up menus in the menu bar.
  1035. This variable must be set before Ediff is loaded. If you don't like the
  1036. look of the default menus, set this variable to nil and make your own
  1037. menus.")  
  1038.  
  1039. (emerge-defvar-local ediff-auto-refine 'on
  1040.   "If `'on', Ediff auto-highlights fine diffs for the current diff region.
  1041. If `off', auto-highlighting is not used. If `'nix', no fine diffs are shown
  1042. at all, unless the user force-refines the region by hitting `*'.
  1043.  
  1044. This variable can be set either in .emacs or toggled interactively, using
  1045. ediff-toggle-hilit.") 
  1046.  
  1047. (emerge-defvar-local ediff-auto-refine-limit 700
  1048.   "Auto-refine only those regions that are smaller than this number of bytes.")
  1049.  
  1050. (emerge-defvar-local ediff-highlight-all-diffs t
  1051.   "If nil, only the selected differences are highlighted.
  1052. This variable can be set either in .emacs or toggled interactively, using
  1053. ediff-toggle-hilit.") 
  1054.  
  1055. (emerge-defvar-local ediff-highlighting-style nil
  1056.   "A var local to each ediff-control buffer.
  1057. Indicates highlighting style in effect for this buffer: `face', `ascii',
  1058. nil -- temporarily unhighlighted, `off' -- turned off \(on a dumb
  1059. terminal only\).")
  1060.  
  1061.   
  1062.  
  1063. ;; Variables that control each Ediff session.  They are local to the
  1064. ;; control buffer. 
  1065.  
  1066. ;; Mode variables
  1067. (emerge-defvar-local ediff-A-buffer nil
  1068.   "The buffer in which the A variant is stored.")
  1069. (emerge-defvar-local ediff-B-buffer nil
  1070.   "The buffer in which the B variant is stored.")
  1071. (emerge-defvar-local ediff-control-buffer nil
  1072.   "The control buffer of ediff. ")
  1073.  
  1074. ;(emerge-defvar-local ediff-control-buffer-suffix nil
  1075. ;  "The suffix of the control buffer name. ")
  1076.   
  1077. (emerge-defvar-local ediff-control-window nil
  1078.   "The control window.")
  1079. (emerge-defvar-local ediff-window-config-saved ""
  1080.   "Ediff's window configuration.
  1081. Used to minimize the need to rearrange windows.")
  1082.  
  1083.  
  1084. (emerge-defvar-local ediff-A-buffer-values nil
  1085.   "Keeps working values of ediff-saved-variables for ediff-A-buffer.")
  1086. (emerge-defvar-local ediff-B-buffer-values nil
  1087.   "Keeps working values of ediff-saved-variables for ediff-B-buffer.")
  1088.  
  1089. (emerge-defvar-local ediff-A-buffer-values-setup nil
  1090.   "Remembers ediff-saved-variables for ediff-A-buffer as they were at setup.")
  1091. (emerge-defvar-local ediff-B-buffer-values-setup nil
  1092.   "Remembers ediff-saved-variables for ediff-B-buffer as they were at setup.")
  1093.  
  1094. (emerge-defvar-local ediff-difference-vector nil
  1095.   "Vector of differences between the variants. 
  1096. Each difference is represented by a vector of two overlays.  The first
  1097. overlays the difference section in the A buffer and the second overlays the
  1098. diff in the B buffer. If a difference section is empty, the corresponding
  1099. overlay's endpoints coincide. ")
  1100.  
  1101. (emerge-defvar-local ediff-current-difference -1
  1102.   "The difference that is currently selected.")
  1103. (emerge-defvar-local ediff-number-of-differences nil
  1104.   "Number of differences found.")
  1105.   
  1106. (emerge-defvar-local ediff-diff-buffer nil
  1107.   "Buffer containing the output of diff, which is used by Ediff to step
  1108. through files.")
  1109. (emerge-defvar-local ediff-tmp-buffer nil
  1110.   "Temporary buffer used for computing fine differences.")
  1111. (emerge-defvar-local ediff-error-buffer nil
  1112.   "Buffer containing the output of diff when diff returns errors.")
  1113.  
  1114. (emerge-defvar-local ediff-this-buffer-control-sessions  nil
  1115.   "List of ediff-control buffers associated with each buffer A/B.")
  1116.  
  1117. (defvar ediff-disturbed-overlays nil
  1118.   "List of difference overlays disturbed by working with the current diff.")
  1119.   
  1120. (defvar ediff-shaded-overlay-priority 
  1121.   (if (ediff-if-lucid)
  1122.       (1+ mouse-highlight-priority)
  1123.     100)        ;; 100 is a kludge. There is a bug in insert-in-front-hooks
  1124.         ;; in Emacs < 19.23. When this is fixed, I will get rid of
  1125.         ;; this kludge.
  1126.   "Priority of non-selected overlays.")
  1127.  
  1128.  
  1129. (if (ediff-if-lucid)
  1130.     (progn
  1131.       (fset 'ediff-overlayp (symbol-function 'extentp))
  1132.       (fset 'ediff-make-overlay (symbol-function 'make-extent))
  1133.       (fset 'ediff-delete-overlay (symbol-function 'delete-extent))
  1134.       (fset 'ediff-overlay-put (symbol-function 'set-extent-property))
  1135.       (fset 'ediff-move-overlay (symbol-function 'set-extent-endpoints))
  1136.       (fset 'ediff-overlay-start (symbol-function 'extent-start-position))
  1137.       (fset 'ediff-overlay-end (symbol-function 'extent-end-position))
  1138.       (fset 'ediff-overlay-get (symbol-function 'extent-property)))
  1139.   (fset 'ediff-overlayp (symbol-function 'overlayp))
  1140.   (fset 'ediff-make-overlay (symbol-function 'make-overlay))
  1141.   (fset 'ediff-delete-overlay (symbol-function 'delete-overlay))
  1142.   (fset 'ediff-overlay-put (symbol-function 'overlay-put))
  1143.   (fset 'ediff-move-overlay (symbol-function 'move-overlay))
  1144.   (fset 'ediff-overlay-start (symbol-function 'overlay-start))
  1145.   (fset 'ediff-overlay-end (symbol-function 'overlay-end))
  1146.   (fset 'ediff-overlay-get (symbol-function 'overlay-get)))
  1147.   
  1148. (if window-system
  1149.     (if (ediff-if-lucid)
  1150.     (progn
  1151.       (fset 'ediff-select-frame (symbol-function 'select-screen))
  1152.       (fset 'ediff-window-frame (symbol-function 'window-screen))
  1153.       (fset 'ediff-display-color-p (symbol-function 'x-color-display-p))
  1154.       (fset 'ediff-valid-color-p (symbol-function 'x-valid-color-name-p))
  1155.       (fset 'ediff-get-face (symbol-function 'get-face)))
  1156.       (fset 'ediff-window-frame (symbol-function 'window-frame))
  1157.       (fset 'ediff-select-frame (symbol-function 'select-frame))
  1158.       (fset 'ediff-display-color-p (symbol-function 'x-display-color-p))
  1159.       
  1160.       ;; This is a temporary fix for OS/2 users
  1161.       ;; pm-win.el in PM-Emacs should be fixed.
  1162.       (if (eq window-system 'pm)
  1163.       (fset 'ediff-valid-color-p 
  1164.         (function (lambda (color) (assoc color pm-color-alist))))
  1165.     (fset 'ediff-valid-color-p (symbol-function 'x-color-defined-p))
  1166.     )
  1167.     
  1168.       (fset 'ediff-get-face (symbol-function 'internal-get-face)))
  1169.   ;; not a window system
  1170.   (fset 'ediff-window-frame (function (lambda (wind) (if wind 1 nil)) ))
  1171.   (fset 'ediff-select-frame (symbol-function 'identity))
  1172.   (fset 'ediff-make-current-diff-overlay (function (lambda (type) nil)))
  1173.   (fset 'ediff-unhighlight-diffs-totally (function (lambda () nil))))
  1174.   
  1175.  
  1176. (if (not window-system)
  1177.     ()
  1178.   (defun ediff-set-face (ground face color)
  1179.     "Sets face foreground/background. If color unavailable, guides the user."
  1180.     (if (ediff-valid-color-p color)
  1181.     (if (eq ground 'foreground)
  1182.         (set-face-foreground face color)
  1183.       (set-face-background face color))
  1184.       (cond ((memq face
  1185.            '(ediff-current-diff-face-A ediff-current-diff-face-B))
  1186.          (copy-face 'highlight face))
  1187.         ((memq face
  1188.            '(ediff-fine-diff-face-A ediff-fine-diff-face-B))
  1189.          (copy-face 'secondary-selection face)
  1190.          (set-face-underline-p face t))
  1191.         ((memq face
  1192.            '(ediff-odd-diff-face-A ediff-odd-diff-face-B
  1193.              ediff-even-diff-face-A ediff-even-diff-face-B))
  1194.          (copy-face 'secondary-selection face)))))
  1195.       
  1196.   (defvar ediff-current-diff-face-A
  1197.     (progn
  1198.       (make-face 'ediff-current-diff-face-A)
  1199.       (or (face-differs-from-default-p 'ediff-current-diff-face-A)
  1200.       (cond ((ediff-display-color-p)
  1201.          (ediff-set-face
  1202.           'foreground 'ediff-current-diff-face-A "firebrick")
  1203.          (ediff-set-face
  1204.           'background 'ediff-current-diff-face-A "pale green"))
  1205.         (t
  1206.          (if (ediff-if-lucid)
  1207.              (copy-face 'modeline 'ediff-current-diff-face-A)
  1208.            (copy-face 'highlight 'ediff-current-diff-face-A))
  1209.          )))
  1210.       (ediff-get-face 'ediff-current-diff-face-A))
  1211.     "Face for highlighting the selected difference in buffer A.")
  1212.  
  1213.   (defvar ediff-current-diff-face-B
  1214.     (progn
  1215.       (make-face 'ediff-current-diff-face-B)
  1216.       (or (face-differs-from-default-p 'ediff-current-diff-face-B)
  1217.       (cond ((ediff-display-color-p)
  1218.          (ediff-set-face
  1219.           'foreground 'ediff-current-diff-face-B "DarkOrchid")
  1220.          (ediff-set-face
  1221.           'background 'ediff-current-diff-face-B "Yellow"))
  1222.         (t 
  1223.          (if (ediff-if-lucid)
  1224.              (copy-face 'modeline 'ediff-current-diff-face-B)
  1225.            (copy-face 'highlight 'ediff-current-diff-face-B))
  1226.          )))
  1227.       (ediff-get-face 'ediff-current-diff-face-B))
  1228.     "Face for highlighting the selected difference in buffer B.")
  1229.  
  1230.   (defvar ediff-fine-diff-face-A
  1231.     (progn
  1232.       (make-face 'ediff-fine-diff-face-A)
  1233.       (or (face-differs-from-default-p 'ediff-fine-diff-face-A)
  1234.       (cond ((ediff-display-color-p)
  1235.          (ediff-set-face 'foreground 'ediff-fine-diff-face-A
  1236.                  "Navy")
  1237.          (ediff-set-face 'background 'ediff-fine-diff-face-A
  1238.                  "sky blue"))
  1239.         (t (set-face-underline-p 'ediff-fine-diff-face-A t))))
  1240.       (ediff-get-face 'ediff-fine-diff-face-A))
  1241.     "Face for highlighting the refinement of the selected diff in buffer A.")
  1242.  
  1243.   (defvar ediff-fine-diff-face-B
  1244.     (progn
  1245.       (make-face 'ediff-fine-diff-face-B)
  1246.       (or (face-differs-from-default-p 'ediff-fine-diff-face-B)
  1247.       (cond ((ediff-display-color-p)
  1248.          (ediff-set-face 'foreground 'ediff-fine-diff-face-B "Black")
  1249.          (ediff-set-face 'background 'ediff-fine-diff-face-B "cyan"))
  1250.         (t (set-face-underline-p 'ediff-fine-diff-face-B t))))
  1251.       (ediff-get-face 'ediff-fine-diff-face-B))
  1252.     "Face for highlighting the refinement of the selected diff in buffer B.")
  1253.  
  1254.  
  1255.   (defvar ediff-even-diff-face-A
  1256.     (progn
  1257.       (make-face 'ediff-even-diff-face-A)
  1258.       (or (face-differs-from-default-p 'ediff-even-diff-face-A)
  1259.       (cond ((ediff-display-color-p)
  1260.          (ediff-set-face
  1261.           'foreground 'ediff-even-diff-face-A "black")
  1262.          (ediff-set-face
  1263.           'background 'ediff-even-diff-face-A "light grey"))
  1264.         (t 
  1265.          (if (ediff-if-lucid)
  1266.              (progn
  1267.                (copy-face 'highlight 'ediff-even-diff-face-A)
  1268.                (invert-face 'ediff-even-diff-face-A))
  1269.            (copy-face 'italic 'ediff-even-diff-face-A)))))
  1270.       (ediff-get-face 'ediff-even-diff-face-A))
  1271.     "Face used to highlight even-numbered differences in buffer A.")
  1272.       
  1273.   (defvar ediff-even-diff-face-B
  1274.     (progn
  1275.       (make-face 'ediff-even-diff-face-B)
  1276.       (or (face-differs-from-default-p 'ediff-even-diff-face-B)
  1277.       (cond ((ediff-display-color-p)
  1278.          (ediff-set-face
  1279.           'foreground 'ediff-even-diff-face-B "White")
  1280.          (ediff-set-face
  1281.           'background 'ediff-even-diff-face-B "Gray"))
  1282.         (t 
  1283.          (if (ediff-if-lucid)
  1284.              (copy-face 'highlight 'ediff-even-diff-face-B)
  1285.            (copy-face 'italic 'ediff-even-diff-face-B)))))
  1286.       (ediff-get-face 'ediff-even-diff-face-B))
  1287.     "Face used to highlight even-numbered differences in buffer B.")
  1288.   
  1289.   (defvar ediff-odd-diff-face-A
  1290.     (progn
  1291.       (make-face 'ediff-odd-diff-face-A)
  1292.       (or (face-differs-from-default-p 'ediff-odd-diff-face-A)
  1293.       (cond ((ediff-display-color-p)
  1294.          (ediff-set-face
  1295.           'foreground 'ediff-odd-diff-face-A "White")
  1296.          (ediff-set-face
  1297.           'background 'ediff-odd-diff-face-A "Gray"))
  1298.         (t 
  1299.          (if (ediff-if-lucid)
  1300.              (copy-face 'highlight 'ediff-odd-diff-face-A)
  1301.            (copy-face 'italic 'ediff-odd-diff-face-A)))))
  1302.       (ediff-get-face 'ediff-odd-diff-face-A))
  1303.     "Face used to highlight odd-numbered differences in buffer A.")
  1304.       
  1305.   (defvar ediff-odd-diff-face-B
  1306.     (progn
  1307.       (make-face 'ediff-odd-diff-face-B)
  1308.       (or (face-differs-from-default-p 'ediff-odd-diff-face-B)
  1309.       (cond ((ediff-display-color-p)
  1310.          (ediff-set-face
  1311.           'foreground 'ediff-odd-diff-face-B "Black")
  1312.          (ediff-set-face
  1313.           'background 'ediff-odd-diff-face-B "light grey"))
  1314.         (t 
  1315.          (if (ediff-if-lucid)
  1316.              (progn
  1317.                (copy-face 'highlight 'ediff-odd-diff-face-B)
  1318.                (invert-face 'ediff-odd-diff-face-B))
  1319.            (copy-face 'italic 'ediff-odd-diff-face-B)))))
  1320.       (ediff-get-face 'ediff-odd-diff-face-B))
  1321.     "Face used to highlight odd-numbered differences in buffer B.")
  1322.  
  1323.   ;; Create *-var faces. These are the actual faces used to highlight
  1324.   ;; odd-numbered difference regions.
  1325.   ;; They are used as follows: when highlighting is turned on,
  1326.   ;; ediff-odd/even-diff-face-A/B are copied
  1327.   ;; into ediff-odd/even-diff-face-A/B-var, and all odd/even overlays become
  1328.   ;; highlighted. When highlighting is turned off, then the face 'default is
  1329.   ;; copied into ediff-odd/even-diff-face-A/B-var, thereby unhighlighting all
  1330.   ;; difference regions.
  1331.   (make-face 'ediff-even-diff-face-A-var)
  1332.   (make-face 'ediff-even-diff-face-B-var)
  1333.   (make-face 'ediff-odd-diff-face-A-var)
  1334.   (make-face 'ediff-odd-diff-face-B-var)
  1335.   
  1336.   ;; initialize *-var faces
  1337.   (defun ediff-init-var-faces ()
  1338.     (copy-face (if (and ediff-want-faces ediff-highlight-all-diffs)
  1339.            ediff-even-diff-face-A 'default)
  1340.            'ediff-even-diff-face-A-var)
  1341.     (copy-face (if (and ediff-want-faces ediff-highlight-all-diffs)
  1342.            ediff-even-diff-face-B 'default)
  1343.            'ediff-even-diff-face-B-var)
  1344.     (copy-face (if (and ediff-want-faces ediff-highlight-all-diffs)
  1345.            ediff-odd-diff-face-A 'default)
  1346.            'ediff-odd-diff-face-A-var)
  1347.     (copy-face (if (and ediff-want-faces ediff-highlight-all-diffs)
  1348.            ediff-odd-diff-face-B 'default)
  1349.            'ediff-odd-diff-face-B-var))
  1350.       
  1351.  
  1352.   ;;; Overlays
  1353.  
  1354.   (emerge-defvar-local ediff-current-diff-overlay-A nil
  1355.     "Overlay in buffer A.")
  1356.   (emerge-defvar-local ediff-current-diff-overlay-B nil
  1357.     "Overlay in buffer B.")
  1358.   
  1359.   (defun ediff-make-current-diff-overlay (type)
  1360.       (let ((overlay (if (eq type 'A)
  1361.              'ediff-current-diff-overlay-A
  1362.                'ediff-current-diff-overlay-B))
  1363.         (buffer (ediff-get-buffer type))
  1364.         (face (if (eq type 'A) 
  1365.               (face-name ediff-current-diff-face-A)
  1366.             (face-name ediff-current-diff-face-B))))
  1367.     (set overlay (ediff-make-overlay (point-max) (point-max) buffer))
  1368.     (ediff-overlay-put (eval overlay) 'face face)
  1369.     (ediff-overlay-put (eval overlay) 'ediff ediff-control-buffer)
  1370.     ))
  1371.     
  1372.   ;; Computes priority of ediff overlay.
  1373.   (defun ediff-highest-priority (start end buffer)
  1374.     (let ((pos (max 1 (1- start)))
  1375.       ovr-list)
  1376.       (if (ediff-if-lucid)
  1377.       (+ 2 mouse-highlight-priority)
  1378.     (emerge-eval-in-buffer
  1379.      buffer
  1380.      (while (< pos (min (point-max) (1+ end)))
  1381.        (setq ovr-list (append (overlays-at pos) ovr-list))
  1382.        (setq pos (next-overlay-change pos)))
  1383.      (1+ (eval
  1384.           (cons '+
  1385.             (mapcar (function
  1386.                  (lambda (ovr)
  1387.                    (if ovr
  1388.                    (or (ediff-overlay-get ovr 'priority) 0)
  1389.                  0)))
  1390.                 ovr-list)
  1391.             )))
  1392.      ))))
  1393.  
  1394. )  ; end of window-system-only code.
  1395.   
  1396.   
  1397.  
  1398. ;;; Misc
  1399.  
  1400. (defvar ediff-split-window-function 'split-window-vertically
  1401.   "*The function to split the main window between buffer-A and buffer-B.
  1402. You can set it to be split horizontally instead of the
  1403. default vertical split by setting this variable to
  1404. 'split-window-horizontally.  You can also have your own function for fancy
  1405. splits.  This variable has no effect when buffer-A and buffer-B are shown in
  1406. different frames.  In this case, Ediff will use those frames to display
  1407. these buffers.")
  1408.          
  1409. (defconst ediff-saved-variables
  1410.   '(buffer-read-only
  1411.     buffer-auto-save-file-name)
  1412.   "Buffer-local variables saved and restored during an Ediff session.")
  1413.  
  1414. (defconst ediff-working-values '(nil nil)
  1415.   "Values to be assigned to `ediff-saved-variables' during diff.")
  1416.   
  1417. (defvar ediff-use-last-dir nil
  1418.   "*If t, Ediff uses previous directory as default when reading file name.")
  1419.   
  1420. (defvar ediff-no-help-in-control-buffer nil
  1421.   "*Non-nil mean C-h should not invoke Emacs help.
  1422. Instead, C-h jumps to previous difference.")
  1423.   
  1424. (defvar ediff-temp-file-prefix
  1425.   (let ((env (getenv "TMPDIR"))
  1426.     d)
  1427.     (setq d (if (and env (> (length env) 0))
  1428.         env
  1429.           "/tmp"))
  1430.     (if (= (aref d (1- (length d))) ?/)
  1431.     (setq d (substring d 0 -1)))
  1432.     (concat d "/ediff"))
  1433.   "*Prefix to put on Ediff temporary file names.
  1434. Do not start with `~/' or `~user-name/'.")  
  1435.  
  1436. (defvar ediff-temp-file-mode 384    ; u=rw only
  1437.   "*Mode for Ediff temporary files.")
  1438.   
  1439. (emerge-defvar-local ediff-temp-file-A nil
  1440.   "Temporary file used for refining difference regions in buffer B.")
  1441. (emerge-defvar-local ediff-temp-file-B nil
  1442.   "Temporary file used for refining difference regions in buffer B.")
  1443.   
  1444. (defvar ediff-last-dir-A nil
  1445.   "Last directory used by an Ediff command for file-A.")
  1446. (defvar ediff-last-dir-B nil
  1447.   "Last directory used by an Ediff command for file-B.")
  1448.   
  1449. ;; Build keymaps
  1450.  
  1451. (defvar ediff-mode-map nil
  1452.   "Local keymap used in Ediff mode.")
  1453.   
  1454. ;;; This is split in three parts to avoid
  1455. ;;; making a line in loaddefs.el that is too long for patch.
  1456. ;;; Note that autoload.el currently looks for cookies
  1457. ;;; only at top level in the file.
  1458. ;;;###autoload
  1459. (progn
  1460.   (defvar menu-bar-epatch-menu (make-sparse-keymap "menu-bar-epatch-map"))
  1461.   (fset 'menu-bar-epatch-menu (symbol-value 'menu-bar-epatch-menu))
  1462.   (defvar menu-bar-ediff-menu (make-sparse-keymap "menu-bar-ediff-map"))
  1463.   (fset 'menu-bar-ediff-menu (symbol-value 'menu-bar-ediff-menu)))
  1464.  
  1465. ;;;###autoload
  1466. (progn
  1467.   (define-key menu-bar-ediff-menu [rcs-ediff]
  1468.     '("With a Revision via RCS ..." . rcs-ediff))
  1469.   (define-key menu-bar-ediff-menu [vc-ediff]
  1470.     '("With a Revision via VC ..." . vc-ediff))
  1471.   (define-key menu-bar-ediff-menu [ediff-buffers]
  1472.     '("Between Buffers ..." . ediff-buffers))
  1473.   (define-key menu-bar-ediff-menu [ediff-files]
  1474.     '("Between Files ..." . ediff-files)))
  1475.  
  1476. ;;;###autoload
  1477. (progn
  1478.   (define-key menu-bar-epatch-menu [ediff-patch-buffer]
  1479.     '("To a Buffer ..." . ediff-patch-buffer))
  1480.   (define-key menu-bar-epatch-menu [ediff-patch-file]
  1481.     '("To a File ..." . ediff-patch-file)))
  1482.  
  1483. (if (and window-system ediff-want-default-menus (ediff-frame-has-menubar))
  1484.     (if (ediff-if-lucid)
  1485.     (progn  ;; Lucid menu bars
  1486.       (defvar ediff-menu
  1487.         '(""
  1488.           ["Between Files ..."  ediff-files t]
  1489.           ["Between Buffers ..." ediff-buffers t]
  1490.           ["With a Revision via VC ..."  vc-ediff t]
  1491.           ["With a Revision via RCS ..."  rcs-ediff t]))
  1492.       (defvar epatch-menu
  1493.         '(""
  1494.           ["To a File ..."  ediff-patch-file t]
  1495.           ["To a Buffer ..." ediff-patch-buffer t]))
  1496.       (add-menu '("File") "Find Differences" 
  1497.             ediff-menu
  1498.             "Delete Screen")
  1499.       (add-menu '("File") "Apply Patch" 
  1500.             epatch-menu
  1501.             "Delete Screen")
  1502.       ;; Displays as a solid horizontal line 
  1503.       (add-menu-item '("File") "---" nil nil "Delete Screen")
  1504.       )))
  1505.  
  1506.  
  1507. (defun ediff-setup-keymap ()
  1508.   "Set up the keymap used in the control buffer of Ediff."
  1509.   (setq ediff-mode-map (make-sparse-keymap))
  1510.   (suppress-keymap ediff-mode-map)
  1511.   
  1512.   (define-key ediff-mode-map "p" 'ediff-previous-difference)
  1513.   (define-key ediff-mode-map "\C-?" 'ediff-previous-difference)
  1514.   (define-key ediff-mode-map "\C-h" (if ediff-no-help-in-control-buffer
  1515.                     'ediff-previous-difference nil))
  1516.   (define-key ediff-mode-map "n" 'ediff-next-difference)
  1517.   (define-key ediff-mode-map " " 'ediff-next-difference)
  1518.   (define-key ediff-mode-map "j" 'ediff-jump-to-difference)
  1519.   (define-key ediff-mode-map "g"  nil)
  1520.   (define-key ediff-mode-map "ga" 'ediff-jump-to-difference-at-point)
  1521.   (define-key ediff-mode-map "gb" 'ediff-jump-to-difference-at-point)
  1522.   (define-key ediff-mode-map "q" 'ediff-quit)
  1523.   (define-key ediff-mode-map "z" 'ediff-suspend)
  1524.   (define-key ediff-mode-map "c" 'ediff-recenter)
  1525.   (define-key ediff-mode-map "s" 'ediff-toggle-split)
  1526.   (define-key ediff-mode-map "h" 'ediff-toggle-hilit)
  1527.   (define-key ediff-mode-map "@" 'ediff-toggle-autorefine)
  1528.   (define-key ediff-mode-map "v" 'ediff-scroll-up)
  1529.   (define-key ediff-mode-map "\C-v" 'ediff-scroll-up)
  1530.   (define-key ediff-mode-map "^" 'ediff-scroll-down)
  1531.   (define-key ediff-mode-map "\M-v" 'ediff-scroll-down)
  1532.   (define-key ediff-mode-map "V" 'ediff-scroll-down)
  1533.   (define-key ediff-mode-map "<" 'ediff-scroll-left)
  1534.   (define-key ediff-mode-map ">" 'ediff-scroll-right)
  1535.   (define-key ediff-mode-map "f" 'ediff-file-names)
  1536.   (define-key ediff-mode-map "l" 'ediff-line-numbers)
  1537.   (define-key ediff-mode-map "?" 'ediff-toggle-help)
  1538.   (define-key ediff-mode-map "!" 'ediff-recompute-diffs)
  1539.   (define-key ediff-mode-map "*" 'ediff-make-fine-diffs)
  1540.   (define-key ediff-mode-map "a"  nil)
  1541.   (define-key ediff-mode-map "ab" 'ediff-diff-to-diff)
  1542.   (define-key ediff-mode-map "b"  nil)
  1543.   (define-key ediff-mode-map "ba" 'ediff-diff-to-diff)
  1544.   (define-key ediff-mode-map "r"  nil)
  1545.   (define-key ediff-mode-map "ra" 'ediff-restore-diff)
  1546.   (define-key ediff-mode-map "rb" 'ediff-restore-diff)
  1547.   (define-key ediff-mode-map "o"   nil)
  1548.   (define-key ediff-mode-map "A"  'ediff-toggle-read-only)
  1549.   (define-key ediff-mode-map "B"  'ediff-toggle-read-only)
  1550.   (define-key ediff-mode-map "w"   nil)
  1551.   (define-key ediff-mode-map "wa"  'ediff-save-buffer)
  1552.   (define-key ediff-mode-map "wb"  'ediff-save-buffer)
  1553.   (define-key ediff-mode-map "k"   nil)
  1554.   (define-key ediff-mode-map "kkk" 'ediff-reload-keymap) ;; for debug
  1555.   ;; Allow ediff-mode-map to be referenced indirectly
  1556.   (fset 'ediff-mode-map ediff-mode-map))
  1557.  
  1558.  
  1559. ;;; Setup functions
  1560.  
  1561. (defun ediff-find-file (file buffer &optional last-dir)
  1562.   "Visits FILE for ediff.
  1563. BUFFER is a variable symbol that is supposed to
  1564. get the buffer into which FILE is read.  LAST-DIR is the directory variable
  1565. symbol where FILE's dir name should be returned.
  1566. Arguments: (file 'buffer &optional 'last-dir)"
  1567.   (if (not (file-readable-p file))
  1568.       (error "File `%s' does not exist or is not readable" file))
  1569.   
  1570.   ;; Record the buffer
  1571.   (set buffer (find-file-noselect file))
  1572.   ;; Record the directory of the file
  1573.   (if last-dir
  1574.       (set last-dir (expand-file-name (file-name-directory file))))
  1575.   
  1576.   ;; Make sure the entire file is seen, and it reflects what is on disk
  1577.   (emerge-eval-in-buffer 
  1578.    (eval buffer)
  1579.    (widen)
  1580.    (let ((temp (file-local-copy file))
  1581.      startup-hooks)
  1582.      (if temp
  1583.      (setq file temp
  1584.            startup-hooks
  1585.            (cons (` (lambda () (delete-file (, file))))
  1586.              startup-hooks))
  1587.        ;; Verify that the file matches the buffer
  1588.        (emerge-verify-file-buffer)))))
  1589.  
  1590. (defun ediff-files-internal (file-A file-B &optional startup-hooks)
  1591.   (let (buffer-A buffer-B)
  1592.     (message "Reading file %s ... " file-A)(sit-for .5)
  1593.     (ediff-find-file file-A 'buffer-A 'ediff-last-dir-A)
  1594.     (message "Reading file %s ... " file-B)(sit-for .5)
  1595.     (ediff-find-file file-B 'buffer-B 'ediff-last-dir-B)
  1596.     (ediff-setup buffer-A file-A buffer-B file-B startup-hooks)))
  1597.   
  1598. (defun ediff-get-patch-buffer (dir)
  1599.   "Obtain patch buffer.  If patch is already in a buffer---use it.
  1600. Else, read patch file into a new buffer."
  1601.   (if (y-or-n-p "Is the patch file already in a buffer? ")
  1602.       (setq ediff-patch-buf
  1603.         (get-buffer (read-buffer "Patch buffer name: " nil t))) ;must match
  1604.     (setq ediff-patch-buf
  1605.       (find-file-noselect (read-file-name "Patch file name: "
  1606.                           dir))))
  1607.   (emerge-eval-in-buffer
  1608.    ediff-patch-buf
  1609.    (toggle-read-only 1))
  1610.   (setq ediff-patch-diagnostics
  1611.     (get-buffer-create "*ediff patch diagnostics*"))
  1612.   (emerge-eval-in-buffer
  1613.    ediff-patch-diagnostics
  1614.    (insert-buffer ediff-patch-buf))
  1615.   )
  1616.  
  1617. ;; Start up Ediff on two files
  1618. (defun ediff-setup (buffer-A file-A buffer-B file-B startup-hooks)
  1619.   (setq file-A (expand-file-name file-A))
  1620.   (setq file-B (expand-file-name file-B))
  1621.   (let* ((control-buffer-name (emerge-unique-buffer-name "*ediff-control" "*"))
  1622.      (control-buffer (emerge-eval-in-buffer
  1623.               buffer-A
  1624.               (get-buffer-create control-buffer-name))))
  1625.     (emerge-eval-in-buffer
  1626.      control-buffer
  1627.      (ediff-mode) ;; in control buffer only
  1628.      (setq buffer-read-only nil)
  1629.      (setq ediff-A-buffer buffer-A)
  1630.      (setq ediff-B-buffer buffer-B)
  1631.      (setq ediff-control-buffer control-buffer)
  1632. ;    (setq ediff-control-buffer-suffix
  1633. ;       (if (string-match "<[0-9]*>" control-buffer-name)
  1634. ;           (substring control-buffer-name
  1635. ;              (match-beginning 0) (match-end 0))
  1636. ;         "<1>"))
  1637.      (setq ediff-error-buffer (get-buffer-create (emerge-unique-buffer-name
  1638.                           "*ediff-errors" "*")))
  1639.      (ediff-remember-buffer-characteristics t) ;; remember at setup
  1640.      
  1641.      (ediff-set-keys)
  1642.      (setq ediff-difference-vector (ediff-setup-diff-regions file-A file-B))
  1643.      (setq ediff-number-of-differences (length ediff-difference-vector))
  1644.      (setq ediff-current-difference -1)
  1645.      (ediff-make-current-diff-overlay 'A)
  1646.      (ediff-make-current-diff-overlay 'B)
  1647.      (if window-system
  1648.      (ediff-init-var-faces))
  1649.      (run-hooks 'ediff-before-setup-windows-hooks)
  1650.      (ediff-setup-windows buffer-A buffer-B control-buffer t)
  1651.          
  1652.      ;; all these must be inside emerge-eval-in-buffer control-buffer,
  1653.      ;; since these vars are local to control-buffer
  1654.      ;; These won't run if there are errors in diff
  1655.      (emerge-eval-in-buffer
  1656.       ediff-A-buffer
  1657.       (run-hooks 'ediff-prepare-buffer-hooks)
  1658.       (add-hook 'local-write-file-hooks 'ediff-block-write-file)
  1659.       (setq before-change-function 'ediff-before-change-guard)
  1660.       ;; add control-buffer to the list of sessions
  1661.       (or (memq control-buffer ediff-this-buffer-control-sessions)
  1662.       (setq ediff-this-buffer-control-sessions
  1663.         (cons control-buffer ediff-this-buffer-control-sessions)))
  1664.       (setq mode-line-buffer-identification '("A: %b")))
  1665.      (emerge-eval-in-buffer
  1666.       ediff-B-buffer
  1667.       (run-hooks 'ediff-prepare-buffer-hooks)
  1668.       (add-hook 'local-write-file-hooks 'ediff-block-write-file)
  1669.       (setq before-change-function 'ediff-before-change-guard)
  1670.       ;; add control-buffer to the list of sessions
  1671.       (or (memq control-buffer ediff-this-buffer-control-sessions)
  1672.       (setq ediff-this-buffer-control-sessions
  1673.         (cons control-buffer ediff-this-buffer-control-sessions)))
  1674.       (setq mode-line-buffer-identification '("B: %b")))
  1675.  
  1676.      (emerge-eval-in-buffer control-buffer
  1677.                 (run-hooks 'startup-hooks 'ediff-startup-hooks)
  1678.                 (setq buffer-read-only t)))))
  1679.  
  1680. ;; Generate the difference vector and overlays for the two files
  1681. ;; With optional arg `refine', create refining difference regions
  1682. (defun ediff-setup-diff-regions (file-A file-B 
  1683.                     &optional use-old refine-region
  1684.                               diff-program diff-options
  1685.                           diff-ok-lines-regexp)
  1686.                           
  1687.   (setq diff-program (or diff-program ediff-diff-program)
  1688.     diff-options (or diff-options ediff-diff-options)
  1689.     diff-ok-lines-regexp
  1690.                  (or diff-ok-lines-regexp ediff-diff-ok-lines-regexp))
  1691.              
  1692.   (or use-old (setq ediff-diff-buffer 
  1693.             (get-buffer-create
  1694.              (emerge-unique-buffer-name "*ediff-diff" "*"))))
  1695.   (emerge-eval-in-buffer
  1696.    ediff-diff-buffer
  1697.    (erase-buffer)
  1698.    ;; shell-command tends to display old shell command buffers even when it
  1699.    ;; puts output in another buffer---probably an Emacs bug.
  1700.    (ediff-kill-buffer-carefully "*Shell Command Output*")
  1701.    (let ((shell-file-name ediff-shell))
  1702.      (if refine-region
  1703.      (message "Refining difference region %d ..." (1+ refine-region))
  1704.        (message "Computing differences ...")(sit-for .5))
  1705.      (shell-command
  1706.       (format "%s %s %s %s"
  1707.           diff-program diff-options
  1708.           (ediff-protect-metachars file-A)
  1709.           (ediff-protect-metachars file-B))
  1710.       t)
  1711.      ))
  1712.   (ediff-prepare-error-list diff-ok-lines-regexp)
  1713.   (if refine-region
  1714.       (message "Refining difference region %d ... Done." (1+ refine-region))
  1715.     (message "Computing differences ... Done.")(sit-for .5))
  1716.   (if refine-region
  1717.       (ediff-convert-diffs-to-overlays-refine
  1718.        ediff-A-buffer ediff-B-buffer
  1719.        (ediff-extract-diffs ediff-diff-buffer)
  1720.        refine-region)
  1721.     (ediff-convert-diffs-to-overlays
  1722.      ediff-A-buffer ediff-B-buffer
  1723.      (ediff-extract-diffs ediff-diff-buffer ediff-A-buffer ediff-B-buffer)))
  1724.   )
  1725.   
  1726.     
  1727. (defun ediff-prepare-error-list (ok-regexp)
  1728.   (let ((diff-buff ediff-diff-buffer))
  1729.     (emerge-eval-in-buffer
  1730.      ediff-error-buffer
  1731.      (erase-buffer)
  1732.      (insert-buffer diff-buff)
  1733.      (delete-matching-lines ok-regexp))))
  1734.  
  1735. ;;; Function to start Ediff by patching a file
  1736.  
  1737. ;;;###autoload
  1738. (defun ediff-patch-file (file-to-patch &optional startup-hooks)
  1739.   "Run Ediff by patching FILE-TP-PATCH."
  1740.   (interactive "fFile to patch: ")
  1741.   
  1742.   (ediff-get-patch-buffer (file-name-directory file-to-patch))
  1743.   (let ((buf (get-file-buffer file-to-patch)))
  1744.     (if buf 
  1745.     (progn
  1746.       (emerge-eval-in-buffer
  1747.        buf
  1748.        (if (buffer-modified-p buf)
  1749.            (if (y-or-n-p 
  1750.             (format 
  1751.              "File '%s' is already in buffer %s.  Save before killing? "
  1752.              file-to-patch (buffer-name buf)))
  1753.            (save-buffer buf)))
  1754.        (set-buffer-modified-p nil))
  1755.       (ediff-kill-buffer-carefully buf))))
  1756.   (emerge-eval-in-buffer
  1757.    ediff-patch-diagnostics
  1758.    (let ((shell-file-name ediff-shell))
  1759.      (message "Applying patch ... ")(sit-for .5)
  1760.      ;; always pass patch the -f option, so it won't ask any questions
  1761.      (shell-command-on-region 
  1762.       (point-min) (point-max)
  1763.       (format "%s %s %s"
  1764.           ediff-patch-program (concat "-f " ediff-patch-options)
  1765.           (expand-file-name file-to-patch))
  1766.       t)
  1767.      (message "Applying patch ... Done.")(sit-for .5)
  1768.      ))
  1769.   (switch-to-buffer ediff-patch-diagnostics)
  1770.   (sit-for 0) ;; synchronize
  1771.   
  1772.   (setq startup-hooks (cons 'ediff-toggle-read-only-A startup-hooks))
  1773.   (if (file-exists-p (format "%s.orig" file-to-patch))
  1774.       (ediff-files
  1775.        (format "%s.orig" file-to-patch) file-to-patch startup-hooks) 
  1776.     (error "Patch failed or didn't modify the original file."))
  1777.   
  1778.   (bury-buffer ediff-patch-diagnostics)
  1779.   (message "Patch diagnostics available in buffer %s."
  1780.           (buffer-name ediff-patch-diagnostics)))
  1781.  
  1782. (defalias 'epatch 'ediff-patch-file)
  1783. (defalias 'epatch-buffer 'ediff-patch-buffer)
  1784.  
  1785. ;;; Function to start Ediff on files
  1786.  
  1787. ;;;###autoload
  1788. (defun ediff-files (file-A file-B &optional startup-hooks)
  1789.   "Run Ediff on a pair files, FILE-A and FILE-B."
  1790.   (interactive
  1791.    (let (f)
  1792.      (list (setq f (ediff-read-file-name "File A to compare" 
  1793.                      (if ediff-use-last-dir
  1794.                          ediff-last-dir-A
  1795.                        default-directory)
  1796.                      nil nil))
  1797.        (ediff-read-file-name "File B to compare" 
  1798.                  (if ediff-use-last-dir
  1799.                      ediff-last-dir-B  nil)
  1800.                  f f)
  1801.        )))
  1802.   (ediff-files-internal file-A 
  1803.             (if (file-directory-p file-B)
  1804.                 (expand-file-name
  1805.                  (file-name-nondirectory file-A) file-B)
  1806.               file-B)
  1807.             startup-hooks))
  1808.  
  1809.  
  1810. (defalias 'ediff 'ediff-files)
  1811.  
  1812.  
  1813. ;;; Function to start Ediff on buffers
  1814.  
  1815. ;;;###autoload
  1816. (defun ediff-buffers (buffer-A buffer-B &optional startup-hooks)
  1817.   "Run Ediff on a pair of buffers, BUFFER-A and BUFFER-B."
  1818.   (interactive "bBuffer A to compare: \nbBuffer B to compare: ")
  1819.   (let (file-A file-B)
  1820.     (emerge-eval-in-buffer
  1821.      buffer-A
  1822.      (setq file-A (ediff-make-temp-file)))
  1823.     (emerge-eval-in-buffer
  1824.      buffer-B
  1825.      (setq file-B (ediff-make-temp-file)))
  1826.     (ediff-setup (get-buffer buffer-A) file-A
  1827.          (get-buffer buffer-B) file-B
  1828.          (cons (` (lambda ()
  1829.                 (delete-file (, file-A))
  1830.                 (delete-file (, file-B))))
  1831.                startup-hooks)
  1832.          )))
  1833.           
  1834. ;;;###autoload
  1835. (defun ediff-patch-buffer (buffer-name &optional startup-hooks)          
  1836.   "Run Ediff by patching BUFFER-NAME."
  1837.   (interactive "bBuffer to patch: ")
  1838.   
  1839.   (let* ((file-buffer (get-buffer buffer-name))
  1840.      (file-name (if file-buffer (buffer-file-name  file-buffer))))
  1841.     (if (not file-name)
  1842.     (error "Buffer %s doesn't exist or doesn't visit any file.  Why patch?"
  1843.            file-name))
  1844.     
  1845.     (ediff-patch-file file-name startup-hooks)))
  1846.       
  1847.  
  1848. ;;; Versions Control functions      
  1849.       
  1850. ;;;###autoload
  1851. (defun vc-ediff (rev)
  1852. ;; Note: this function will work only with Emacs 19.22 and higher.
  1853.   "Run ediff on version REV of the current buffer in another window.
  1854. If the current buffer is named `F', the version is named `F.~REV~'.
  1855. If `F.~REV~' already exists, it is used instead of being re-created."
  1856.   (interactive "sVersion to ediff with (default is the latest version): ")
  1857.   (or (featurep 'vc)
  1858.       (if (locate-library "vc") ;; if vc.el is available
  1859.       (progn
  1860.         (require 'vc-hooks) 
  1861.         (define-key vc-prefix-map "=" 'vc-ediff))
  1862.     (error "The VC package is apparently not installed.")))
  1863.   (let ((newvers (current-buffer))
  1864.     (oldvers (vc-version-other-window rev)))
  1865.     ;; current-buffer is supposed to contain the old version in another
  1866.     ;; window
  1867.     (ediff-buffers newvers (current-buffer)) 
  1868.     ))
  1869.     
  1870. (defun rcs-ediff-view-revision (&optional rev)
  1871.   "View previous RCS revision of current file.
  1872. With prefix argument, prompts for a revision name." 
  1873.   (interactive (list (if current-prefix-arg 
  1874.              (read-string "Revision: "))))
  1875.   (let* ((filename (buffer-file-name (current-buffer)))
  1876.      (switches (append '("-p")
  1877.                (if rev (list (concat "-r" rev)) nil)))
  1878.      (buff (concat (file-name-nondirectory filename) ".~" rev "~")))
  1879.     (message "Working...")
  1880.     (setq filename (expand-file-name filename))
  1881.     (with-output-to-temp-buffer
  1882.     buff
  1883.       (let ((output-buffer (ediff-rcs-get-output-buffer filename buff)))
  1884.     (delete-windows-on output-buffer)
  1885.     (save-excursion
  1886.       (set-buffer output-buffer)
  1887.       (apply 'call-process "co" nil t nil
  1888.          ;; -q: quiet (no diagnostics)
  1889.          (append switches rcs-default-co-switches
  1890.              (list "-q" filename))))) 
  1891.       (message "")
  1892.       buff)))    
  1893.       
  1894. (defun ediff-rcs-get-output-buffer (file name)
  1895.   ;; Get a buffer for RCS output for FILE, make it writable and clean it up.
  1896.   ;; Optional NAME is name to use instead of `*RCS-output*'.
  1897.   ;; This is a mofified version from rcs.el v1.1. I use it here to make
  1898.   ;; Ediff immune to changes in rcs.el
  1899.   (let* ((default-major-mode 'fundamental-mode);; no frills!
  1900.      (buf (get-buffer-create name)))
  1901.     (save-excursion
  1902.       (set-buffer buf)
  1903.       (setq buffer-read-only nil
  1904.         default-directory (file-name-directory (expand-file-name file)))
  1905.       (erase-buffer))
  1906.     buf))
  1907.  
  1908. ;;;###autoload
  1909. (defun rcs-ediff (&optional rev)
  1910.   "Run Ediff on the current buffer, comparing it with previous RCS revision.  
  1911. With prefix argument, prompts for revision name." 
  1912.   (interactive (list (if current-prefix-arg 
  1913.              (read-string "Revision: "))))
  1914.   (or (featurep 'rcs)
  1915.       (if (locate-library "rcs")      
  1916.       (progn
  1917.         (require 'rcs)
  1918.         (global-set-key "\C-cD" 'rcs-ediff))
  1919.     (error "The RCS package is apparently not installed.")))
  1920.   (let ((newvers (current-buffer))
  1921.     (oldvers (rcs-ediff-view-revision rev)))
  1922.     (ediff-buffers newvers oldvers)
  1923.     ))
  1924.  
  1925.  
  1926. ;;; Functions to start Ediff via remote request
  1927.  
  1928. ;;;###autoload
  1929. (defun ediff-files-remote (file-a file-b)
  1930.   "Run Ediff on remote files, FILE-A and FILE-B."
  1931.   (ediff-files-internal file-a file-b nil)
  1932.   (throw 'client-wait nil))
  1933.  
  1934.  
  1935. (defun ediff-remote-exit (exit-func)
  1936.   "Exit remote Ediff session."
  1937.   (ediff-really-quit)
  1938.   (funcall exit-func))
  1939.  
  1940.  
  1941.  
  1942. ;; Select the lowest window on the frame.
  1943. (defun ediff-select-lowest-window ()
  1944.   (let* ((lowest-window (selected-window))
  1945.      (bottom-edge (car (cdr (cdr (cdr (window-edges))))))
  1946.          (last-window (previous-window))
  1947.          (window-search t))
  1948.     (while window-search
  1949.       (let* ((this-window (next-window))
  1950.              (next-bottom-edge (car (cdr (cdr (cdr 
  1951.                                                (window-edges this-window)))))))
  1952.         (if (< bottom-edge next-bottom-edge)
  1953.             (progn
  1954.               (setq bottom-edge next-bottom-edge)
  1955.               (setq lowest-window this-window)))
  1956.  
  1957.         (select-window this-window)
  1958.         (if (eq last-window this-window)
  1959.             (progn
  1960.               (select-window lowest-window)
  1961.               (setq window-search nil)))))))
  1962.  
  1963. ;;; Common setup routines
  1964.  
  1965. ;; Set up the window configuration.  If POS is given, set the points to
  1966. ;; the beginnings of the buffers.
  1967. (defun ediff-setup-windows (buffer-A buffer-B control-buffer &optional pos)
  1968.   ;; Make sure we are not in the minibuffer window when we try to delete
  1969.   ;; all other windows.
  1970.   (if (eq (selected-window) (minibuffer-window))
  1971.       (other-window 1))
  1972.   (or (ediff-leave-window-config control-buffer)
  1973.       (progn
  1974.     (delete-other-windows)
  1975.     (switch-to-buffer control-buffer)
  1976.     (ediff-refresh-mode-line)
  1977.   
  1978.     (ediff-arrange-buffer buffer-A buffer-B (current-buffer) pos)
  1979.     (ediff-arrange-buffer buffer-B buffer-A (current-buffer) pos)
  1980.     ;; ediff-arrange-buffer always leaves in ctl buffer
  1981.     ;; setup ctl wind if it is not set.
  1982.     (ediff-setup-control-window)
  1983.   
  1984.     ;; If diff reports errors, show them then quit.
  1985.     (if (/= 0 (emerge-eval-in-buffer ediff-error-buffer (buffer-size)))
  1986.         (let ((diff-output-buf  ediff-diff-buffer))
  1987.           (switch-to-buffer ediff-error-buffer)
  1988.           (ediff-kill-buffer-carefully control-buffer)
  1989.           (error "Errors found in diff output.  Diff output buffer is %s"
  1990.              diff-output-buf))))))
  1991.  
  1992.  
  1993. ;; Arranges goal-buf on the screen.
  1994. (defun ediff-arrange-buffer (goal-buf other-buf ctl-buf &optional pos)
  1995.   (let* ((ctl-wind (get-buffer-window ctl-buf t))
  1996.      (goal-wind (get-buffer-window goal-buf t))
  1997.      (other-wind (get-buffer-window other-buf t))
  1998.      (ctl-frame (ediff-window-frame ctl-wind))
  1999.      (goal-frame (if goal-wind (ediff-window-frame goal-wind)))
  2000.      (other-frame (if other-wind (ediff-window-frame other-wind)))
  2001.      (ctl-frame-shared (or (eq ctl-frame goal-frame)
  2002.                    (eq ctl-frame other-frame))))
  2003.               
  2004.     (cond ((and goal-frame (not (eq goal-wind other-wind)))
  2005.                 ;; goal buffer is visible and we are not comparing file
  2006.             ;; against itself (by mistake).
  2007.             ;; Note:  goal-frame != ctl-frame, as we deleted other
  2008.             ;; windows  on ctl-frame.
  2009.                   (ediff-select-frame goal-frame)
  2010.               (select-window goal-wind)
  2011.               (delete-other-windows)) 
  2012.                                           
  2013.       ;; goal-buf invisible, ctl-frame has only ctl-buf
  2014.       ;; then put goal-buf on ctl-frame
  2015.       ((null ctl-frame-shared)
  2016.               (ediff-select-frame ctl-frame)
  2017.               (split-window-vertically)
  2018.               (ediff-select-lowest-window)
  2019.               (setq ctl-wind (selected-window))
  2020.               (switch-to-buffer ctl-buf)
  2021.               (ediff-setup-control-window)
  2022.               (other-window 1)
  2023.               (switch-to-buffer goal-buf)) ; goal-buf set
  2024.       ;; goal-buf invisible, ctl-frame has ctl-buf and other-buf
  2025.       ;; So, put everything in one frame
  2026.       (other-frame   ;; share with the other buf
  2027.                    (ediff-select-frame ctl-frame)
  2028.                (select-window other-wind)
  2029.                (funcall ediff-split-window-function)
  2030.                (other-window 1)
  2031.                (switch-to-buffer goal-buf))
  2032.       (t ;; debug
  2033.        (error "Funny window combination (Ediff bug?)")))
  2034.  
  2035.       (if pos
  2036.       (goto-char (point-min)))
  2037.       
  2038.       (ediff-select-frame ctl-frame)
  2039.       (select-window ctl-wind)
  2040.       (switch-to-buffer ctl-buf)))
  2041.       
  2042. ;; This function assumes that we are in the window where control buffer is
  2043. ;; to reside.
  2044. (defun ediff-setup-control-window ()
  2045.   "Set up window for control buffer."
  2046.   (erase-buffer)
  2047.   (insert ediff-help-message)
  2048.   (shrink-window-if-larger-than-buffer)
  2049.   (setq ediff-control-window (selected-window))
  2050.   (setq ediff-window-config-saved
  2051.     (format "%S%S%S%S"
  2052.         ediff-control-window
  2053.         (get-buffer-window ediff-A-buffer t)
  2054.         (get-buffer-window ediff-B-buffer t)
  2055.         ediff-split-window-function))
  2056.   (goto-char (point-min))
  2057.   (skip-chars-forward ediff-whitespace))
  2058.   
  2059. (defun ediff-leave-window-config (control-buf)
  2060.   (and (eq control-buf (current-buffer))
  2061.        (/= (buffer-size) 0)
  2062.        (emerge-eval-in-buffer
  2063.     control-buf
  2064.     (string= ediff-window-config-saved
  2065.          (format "%S%S%S%S"
  2066.              (get-buffer-window ediff-control-buffer t)
  2067.              (get-buffer-window ediff-A-buffer t)
  2068.              (get-buffer-window ediff-B-buffer t)
  2069.              ediff-split-window-function)))))
  2070.       
  2071.  
  2072. ;; Set up the keymap in the control buffer
  2073. (defun ediff-set-keys ()
  2074.   "Set up Ediff keymap, if necessary."
  2075.   (if (null ediff-mode-map)
  2076.       (ediff-setup-keymap))
  2077.   (use-local-map ediff-mode-map))
  2078.   
  2079. ;; Reload Ediff keymap.  For debugging only.
  2080. (defun ediff-reload-keymap ()
  2081.   (interactive)
  2082.   (setq ediff-mode-map nil)
  2083.   (ediff-set-keys))
  2084.  
  2085. (defun ediff-before-change-guard (start end)
  2086.   "If buffer is highlighted with ASCII flags, remove highlighting.
  2087. Arguments, START and END are not used, but are provided
  2088. because this is required by `before-change-function'."
  2089.   (let (rehighlight-key)
  2090.     (save-window-excursion
  2091.       (mapcar
  2092.        (function
  2093.     (lambda (buf)
  2094.       (if (ediff-buffer-live-p buf)
  2095.           (emerge-eval-in-buffer
  2096.            buf
  2097.            (if (eq ediff-highlighting-style 'ascii)
  2098.            (progn
  2099.              (ediff-unselect-and-select-difference
  2100.               ediff-current-difference 
  2101.               'unselect-only 'no-recenter)
  2102.              (setq rehighlight-key
  2103.                (substitute-command-keys "\\[ediff-recenter]"))
  2104.              ))))))
  2105.        ediff-this-buffer-control-sessions)
  2106.       (if rehighlight-key
  2107.       (error 
  2108.        "ASCII flags removed. You can edit now. Hit %S to rehighlight."
  2109.        rehighlight-key))
  2110.      )))
  2111.      
  2112. (defun ediff-recompute-diffs ()
  2113.   "Recompute difference regions in buffers A and B."
  2114.   (interactive)
  2115.   (let ((curr-diff ediff-current-difference)
  2116.     (point-A (emerge-eval-in-buffer ediff-A-buffer (point)))
  2117.     (point-B (emerge-eval-in-buffer ediff-B-buffer (point)))
  2118.     file-A file-B)
  2119.     (ediff-unselect-and-select-difference -1)
  2120.     (emerge-eval-in-buffer
  2121.      ediff-A-buffer
  2122.      (setq file-A (ediff-make-temp-file)))
  2123.     (emerge-eval-in-buffer
  2124.      ediff-B-buffer
  2125.      (setq file-B (ediff-make-temp-file)))
  2126.     (ediff-clear-diff-vector ediff-difference-vector 'fine-diffs-also)
  2127.     (setq ediff-killed-diffs-alist nil) ; saved kills will no longer be valid
  2128.                                         ; after recompute
  2129.     (setq ediff-difference-vector
  2130.       (ediff-setup-diff-regions file-A file-B 'use-old))
  2131.     (setq ediff-number-of-differences (length ediff-difference-vector))
  2132.     (delete-file file-A)
  2133.     (delete-file file-B)
  2134.     (emerge-eval-in-buffer ediff-A-buffer (goto-char point-A))
  2135.     (ediff-jump-to-difference (ediff-diff-at-point 'A))
  2136.     (beep 1)
  2137.     (if (y-or-n-p 
  2138.     "Ediff is around last posn in buff A. Stay (or goto last posn in B)? ")
  2139.     ()
  2140.       (emerge-eval-in-buffer ediff-B-buffer (goto-char point-B))
  2141.       (ediff-jump-to-difference (ediff-diff-at-point 'B)))
  2142.     (message "")
  2143.     ))
  2144.  
  2145. (defun ediff-remember-buffer-characteristics (&optional arg)
  2146.   "Record certain properties of the buffers being compared.
  2147. Must be called in the control buffer.  Saves `read-only', `modified',
  2148. and `auto-save' properties in buffer local variables.  Turns off
  2149. `auto-save-mode'.  These properties are restored via a call to
  2150. `ediff-restore-buffer-characteristics'."
  2151.  
  2152.   ;; remember and alter buffer characteristics
  2153.   (set  (if arg 'ediff-A-buffer-values-setup 'ediff-A-buffer-values)
  2154.     (emerge-eval-in-buffer
  2155.      ediff-A-buffer
  2156.      (prog1
  2157.          (emerge-save-variables ediff-saved-variables)
  2158.        (emerge-restore-variables ediff-saved-variables
  2159.                      ediff-working-values))))
  2160.   (set  (if arg 'ediff-B-buffer-values-setup 'ediff-B-buffer-values)
  2161.     (emerge-eval-in-buffer
  2162.      ediff-B-buffer
  2163.      (prog1
  2164.          (emerge-save-variables ediff-saved-variables)
  2165.        (emerge-restore-variables ediff-saved-variables
  2166.                      ediff-working-values)))))
  2167.  
  2168. (defun ediff-restore-buffer-characteristics (&optional arg)
  2169.   "Restores properties saved by `ediff-remember-buffer-characteristics'."
  2170.   (let ((A-values (if arg ediff-A-buffer-values-setup ediff-A-buffer-values))
  2171.     (B-values (if arg ediff-B-buffer-values-setup ediff-B-buffer-values)))
  2172.     (emerge-eval-in-buffer ediff-A-buffer
  2173.                (emerge-restore-variables ediff-saved-variables
  2174.                              A-values))
  2175.     (emerge-eval-in-buffer ediff-B-buffer
  2176.                (emerge-restore-variables ediff-saved-variables
  2177.                              B-values))))
  2178.  
  2179.  
  2180. ;; if optional A-buffer and B-buffer are given, then construct a vector of
  2181. ;; diff using point values. Otherwise, use line offsets.
  2182. (defun ediff-extract-diffs (diff-buffer &optional A-buffer B-buffer)
  2183.   (let (diff-list
  2184.     (a-prev 1) ;; this is needed to set the first diff line correctly
  2185.     (b-prev 1))
  2186.  
  2187.     (if (and A-buffer B-buffer)
  2188.     (progn    ;; reset point in buffers A and B
  2189.       (emerge-eval-in-buffer
  2190.        A-buffer
  2191.        (goto-char (point-min)))
  2192.       (emerge-eval-in-buffer
  2193.        B-buffer
  2194.        (goto-char (point-min)))))
  2195.     
  2196.     (emerge-eval-in-buffer
  2197.      diff-buffer
  2198.      (goto-char (point-min))
  2199.      (while (re-search-forward ediff-match-diff-line nil t)
  2200.        (let* ((a-begin (string-to-int (buffer-substring (match-beginning 1)
  2201.                             (match-end 1))))
  2202.           (a-end  (let ((b (match-beginning 3))
  2203.                 (e (match-end 3)))
  2204.             (if b
  2205.                 (string-to-int (buffer-substring b e))
  2206.               a-begin)))
  2207.           (diff-type (buffer-substring (match-beginning 4) (match-end 4)))
  2208.           (b-begin (string-to-int (buffer-substring (match-beginning 5)
  2209.                             (match-end 5))))
  2210.           (b-end (let ((b (match-beginning 7))
  2211.                (e (match-end 7)))
  2212.                (if b
  2213.                (string-to-int (buffer-substring b e))
  2214.              b-begin)))
  2215.           a-begin-pt a-end-pt b-begin-pt b-end-pt)
  2216.      ;; fix the beginning and end numbers, because diff is somewhat
  2217.      ;; strange about how it numbers lines
  2218.      (if (string-equal diff-type "a")
  2219.          (setq b-end (1+ b-end)
  2220.            a-begin (1+ a-begin)
  2221.            a-end a-begin)
  2222.        (if (string-equal diff-type "d")
  2223.            (setq a-end (1+ a-end)
  2224.              b-begin (1+ b-begin)
  2225.              b-end b-begin)
  2226.          ;; (string-equal diff-type "c")
  2227.          (setq a-end (1+ a-end)
  2228.            b-end (1+ b-end))))
  2229.      (if (and A-buffer B-buffer)
  2230.          (progn    ;; computing main diff vector
  2231.            ;; convert to relative line numbers    
  2232.            (emerge-eval-in-buffer
  2233.         A-buffer
  2234.         (forward-line (- a-begin a-prev))
  2235.         (setq a-begin-pt (point))
  2236.         (forward-line (- a-end a-begin))
  2237.         (setq a-end-pt (point)
  2238.               a-prev a-end))
  2239.            (emerge-eval-in-buffer
  2240.         B-buffer
  2241.         (forward-line (- b-begin b-prev))
  2242.         (setq b-begin-pt (point))
  2243.         (forward-line (- b-end b-begin))
  2244.         (setq b-end-pt (point)
  2245.               b-prev b-end))
  2246.            (setq diff-list 
  2247.              (nconc diff-list (list (vector a-begin-pt a-end-pt
  2248.                             b-begin-pt b-end-pt)))))
  2249.        ;; computing refinement vector
  2250.        (setq  diff-list 
  2251.           (nconc diff-list (list (vector (- a-begin a-prev)
  2252.                          (- a-end a-begin)
  2253.                          (- b-begin b-prev)
  2254.                          (- b-end b-begin))))
  2255.           a-prev a-end
  2256.           b-prev b-end))
  2257.           
  2258.      ))) ;; end emerge-eval-in-buffer
  2259.     diff-list
  2260.     ))
  2261.     
  2262. (defun ediff-convert-diffs-to-overlays (A-buffer B-buffer diff-list)
  2263.   (let* ((current-diff -1)
  2264.      (total-diffs (length diff-list))
  2265. ;     (control-buffer-suffix ediff-control-buffer-suffix)
  2266.      diff-overlay-list list-element
  2267.      a-begin a-end b-begin b-end
  2268.      a-overlay b-overlay)
  2269.  
  2270.     (while diff-list
  2271.       (setq current-diff (1+ current-diff)
  2272.         list-element (car diff-list)
  2273.         a-begin      (aref list-element 0)
  2274.         a-end      (aref list-element 1)
  2275.         b-begin      (aref list-element 2)
  2276.         b-end      (aref list-element 3))
  2277.         
  2278.       ;; place overlays at the appropriate places in the buffers
  2279.       (setq a-overlay (ediff-make-overlay a-begin a-end A-buffer))
  2280.       ;; priorities of overlays should be equal in all ediff-control
  2281.       ;; buffers. otherwise it won't work due to Emacs
  2282.       ;; bug---insert-in-front-hooks will be called 
  2283.       ;; only on behalf of the buffer with higher priority.
  2284.       (ediff-overlay-put a-overlay 'priority ediff-shaded-overlay-priority)
  2285.       (ediff-overlay-put a-overlay 'ediff-diff-num current-diff)
  2286.       (ediff-overlay-put a-overlay
  2287.              'insert-in-front-hooks '(ediff-insert-in-front))
  2288. ;     (ediff-overlay-put a-overlay
  2289. ;             'ediff-control-buffer control-buffer-suffix)
  2290.       (ediff-overlay-put a-overlay 
  2291.              'face (if (ediff-odd-p current-diff) ;; odd diff
  2292.                    'ediff-odd-diff-face-A-var
  2293.                  'ediff-even-diff-face-A-var))
  2294.              
  2295.       (setq b-overlay (ediff-make-overlay b-begin b-end B-buffer))
  2296.       (ediff-overlay-put b-overlay 'priority ediff-shaded-overlay-priority)
  2297.       (ediff-overlay-put b-overlay 'ediff-diff-num current-diff)
  2298.       (ediff-overlay-put b-overlay
  2299.              'insert-in-front-hooks '(ediff-insert-in-front))
  2300. ;     (ediff-overlay-put b-overlay
  2301. ;             'ediff-control-buffer control-buffer-suffix)
  2302.       (ediff-overlay-put b-overlay 
  2303.              'face (if (ediff-odd-p current-diff) ;; odd diff
  2304.                    'ediff-odd-diff-face-B-var
  2305.                  'ediff-even-diff-face-B-var))
  2306.                  
  2307.       (if (ediff-if-lucid) ;; chars inserted at end will be inside extent
  2308.       (progn
  2309.         (ediff-overlay-put a-overlay
  2310.                    'ediff-marker 
  2311.                    (move-marker (make-marker) a-begin A-buffer))
  2312.         (ediff-overlay-put b-overlay
  2313.                    'ediff-marker 
  2314.                    (move-marker (make-marker) b-begin B-buffer))
  2315.         (ediff-overlay-put a-overlay 'end-open nil)
  2316.         (ediff-overlay-put b-overlay 'end-open nil)))
  2317.              
  2318.       ;; record all overlays for this difference
  2319.       (setq diff-overlay-list
  2320.         (nconc diff-overlay-list (list (vector a-overlay b-overlay nil)))
  2321.         diff-list (cdr diff-list))
  2322.       (message "Processing diff region %d of %d"
  2323.            current-diff total-diffs)
  2324.       ) ;; while
  2325.     ;; this is just to avoid confusing the user with diff num < total-diffs
  2326.     (message "Processing diff region %d of %d"
  2327.            (1+ current-diff) total-diffs)
  2328.     ;; convert the list of difference information into a vector for
  2329.     ;; fast access
  2330.     (apply 'vector diff-overlay-list)))
  2331.  
  2332.  
  2333.  
  2334. ;;; Commands
  2335.  
  2336. (defun ediff-recenter (&optional no-rehighlight)
  2337.   "Bring the highlighted region of all buffers A and B into view.
  2338. Reestablish the default three-window display."
  2339.   (interactive)
  2340.   (setq ediff-disturbed-overlays nil) ;; clear after use
  2341.   (let (buffer-read-only)
  2342.     (ediff-setup-windows ediff-A-buffer ediff-B-buffer ediff-control-buffer))
  2343.   ;; Redisplay whatever buffers are showing, if there is a selected difference
  2344.   (if (and (>= ediff-current-difference 0)
  2345.        (< ediff-current-difference ediff-number-of-differences))
  2346.       (let* ( ;; context must be saved before switching to windows A/B
  2347.          (buffer-A ediff-A-buffer)
  2348.          (buffer-B ediff-B-buffer)
  2349.          (wind (selected-window))
  2350.          (control-buf ediff-control-buffer)
  2351.          (before-flag-shift-A (if (eq ediff-highlighting-style 'ascii)
  2352.                       (1- (length ediff-before-flag-A))
  2353.                     0))
  2354.          (after-flag-shift-A (if (eq ediff-highlighting-style 'ascii)
  2355.                      (1- (length ediff-after-flag-A))
  2356.                    0))
  2357.          (before-flag-shift-B (if (eq ediff-highlighting-style 'ascii)
  2358.                       (1- (length ediff-before-flag-B))
  2359.                     0))
  2360.          (after-flag-shift-B (if (eq ediff-highlighting-style 'ascii)
  2361.                      (1- (length ediff-after-flag-B))
  2362.                    0))
  2363.          (window-A (get-buffer-window buffer-A t))
  2364.          (window-B (get-buffer-window buffer-B t)))
  2365.     
  2366.     (or no-rehighlight
  2367.         (ediff-operate-on-flags 'insert))
  2368.         
  2369.     (if window-A (progn
  2370.                (select-window window-A)
  2371.                (ediff-position-region
  2372.             (- (ediff-get-diff-posn 'A 'beg nil control-buf)
  2373.                before-flag-shift-A)
  2374.             (+ (ediff-get-diff-posn 'A 'end nil control-buf)
  2375.                after-flag-shift-A)
  2376.             (ediff-get-diff-posn 'A 'beg nil control-buf))))
  2377.     (if window-B (progn
  2378.                (select-window window-B)
  2379.                (ediff-position-region
  2380.             (- (ediff-get-diff-posn 'B 'beg nil control-buf)
  2381.                before-flag-shift-B)
  2382.             (+ (ediff-get-diff-posn 'B 'end nil control-buf)
  2383.                after-flag-shift-B)
  2384.             (ediff-get-diff-posn 'B 'beg nil control-buf))))
  2385.     (select-window wind))))
  2386.     
  2387. (defun ediff-toggle-split ()
  2388.   "Toggle vertical/horizontal window split. 
  2389. Does nothing if file-A and file-B are in different frames."
  2390.   (interactive)
  2391.   (let* ((wind-A (get-buffer-window ediff-A-buffer t))
  2392.      (wind-B (get-buffer-window ediff-B-buffer t))
  2393.      (frame-A (if wind-A (ediff-window-frame wind-A)))
  2394.      (frame-B (if wind-B (ediff-window-frame wind-B))))
  2395.     (if (eq frame-A frame-B)
  2396.     (setq ediff-split-window-function
  2397.           (if (eq ediff-split-window-function 'split-window-vertically)
  2398.           'split-window-horizontally
  2399.         'split-window-vertically))
  2400.       (message "No splitting: Buffers A and B are in different frames."))
  2401.     (ediff-recenter 'no-rehighlight)))
  2402.   
  2403. (defun ediff-toggle-hilit ()
  2404.   "Switch between highlighting using ASCII flags and highlighting using faces.
  2405. On a dumb terminal, switches between ASCII highlighting and no highlighting." 
  2406.   (interactive)
  2407.   (if (not window-system)
  2408.       (if (eq ediff-highlighting-style 'ascii)
  2409.       (progn
  2410.         (message "ASCII highlighting flags removed.")
  2411.         (ediff-unselect-and-select-difference ediff-current-difference
  2412.                           'unselect-only)
  2413.         (setq ediff-highlighting-style 'off))
  2414.     (ediff-unselect-and-select-difference ediff-current-difference
  2415.                           'select-only))
  2416.     (ediff-unselect-and-select-difference ediff-current-difference
  2417.                       'unselect-only)
  2418.     ;; cycle through highlighting
  2419.     (cond ((and ediff-want-faces ediff-highlight-all-diffs)
  2420.        (message "Unhighlighting unselected difference regions.")
  2421.        (setq ediff-highlight-all-diffs nil))
  2422.       (ediff-want-faces
  2423.        (message "Highlighting with ASCII flags.")
  2424.        (setq ediff-want-faces nil))
  2425.       (t
  2426.        (message "Re-highlighting all difference regions.")
  2427.        (setq ediff-want-faces t
  2428.          ediff-highlight-all-diffs t)))
  2429.          
  2430.     (if (and ediff-want-faces ediff-highlight-all-diffs)
  2431.     (if (not (face-differs-from-default-p 'ediff-odd-diff-face-A-var))
  2432.         (progn
  2433.           (copy-face ediff-odd-diff-face-A 'ediff-odd-diff-face-A-var)
  2434.           (copy-face ediff-odd-diff-face-B 'ediff-odd-diff-face-B-var)
  2435.           (copy-face ediff-even-diff-face-A 'ediff-even-diff-face-A-var)
  2436.           (copy-face ediff-even-diff-face-B 'ediff-even-diff-face-B-var)))
  2437.       (copy-face 'default 'ediff-odd-diff-face-A-var)
  2438.       (copy-face 'default 'ediff-odd-diff-face-B-var)
  2439.       (copy-face 'default 'ediff-even-diff-face-A-var)
  2440.       (copy-face 'default 'ediff-even-diff-face-B-var))
  2441.     
  2442.     (ediff-unselect-and-select-difference
  2443.      ediff-current-difference 'select-only))
  2444.   (ediff-operate-on-flags 'insert)
  2445.   )
  2446.   
  2447. (defun ediff-toggle-autorefine ()
  2448.   "Toggle auto-refine mode."
  2449.   (interactive)
  2450.   (if window-system
  2451.       (cond ((eq ediff-auto-refine 'nix)
  2452.          (setq ediff-auto-refine 'on)
  2453.          (ediff-make-fine-diffs ediff-current-difference 'noforce)
  2454.          (message "Auto-refining is ON."))
  2455.         ((eq ediff-auto-refine 'on)
  2456.          (message "Auto-refining is OFF.")
  2457.          (setq ediff-auto-refine 'off))
  2458.         (t
  2459.          (ediff-set-fine-diff-properties ediff-current-difference 'default)
  2460.          (message "Refinements are HIDDEN.")
  2461.          (setq ediff-auto-refine 'nix))
  2462.         )))
  2463.   
  2464. (defun ediff-toggle-help ()
  2465.   "Toggle short/long help message."
  2466.   (interactive)
  2467.   (let (buffer-read-only)
  2468.     (erase-buffer)
  2469.     (if (string= ediff-help-message ediff-help-message-long)
  2470.     (setq ediff-help-message ediff-help-message-short)
  2471.       (setq ediff-help-message ediff-help-message-long)))
  2472.   (setq ediff-window-config-saved "") ;; force redisplay
  2473.   (ediff-recenter 'no-rehighlight))
  2474.   
  2475.   
  2476. (defun ediff-toggle-read-only-A ()
  2477.   "Used as a startup hook to set `.orig' patch file read-only."
  2478.   (let ((last-command-char ?A))
  2479.     (ediff-toggle-read-only)))
  2480.   
  2481. (defun ediff-toggle-read-only ()
  2482.   "Toggles buffer-read-only for buffer buffers A and B."
  2483.   (interactive)
  2484.   (emerge-eval-in-buffer
  2485.    (if (eq last-command-char ?A) ediff-A-buffer ediff-B-buffer)
  2486.    (setq buffer-read-only (null buffer-read-only))))
  2487.  
  2488. ;;; Window scrolling operations
  2489. ;; These operations are designed to scroll all three windows the same amount,
  2490. ;; so as to keep the text in them aligned.
  2491.  
  2492. ;; Perform some operation on the two file windows (if they are showing).
  2493. ;; Catches all errors on the operation in the A and B windows.
  2494. ;; Usually, errors come from scrolling off the
  2495. ;; beginning or end of the buffer, and this gives nice nice error messages.
  2496. (defun ediff-operate-on-windows (operation arg)
  2497.   (let* ((buffer-A ediff-A-buffer)
  2498.      (buffer-B ediff-B-buffer)
  2499.      (wind (selected-window))
  2500.      (window-A (get-buffer-window buffer-A t))
  2501.      (window-B (get-buffer-window buffer-B t)))
  2502.       (if window-A (progn
  2503.              (select-window window-A)
  2504.              (condition-case nil
  2505.              (funcall operation arg)
  2506.                (error))))
  2507.       (if window-B (progn
  2508.              (select-window window-B)
  2509.              (condition-case nil
  2510.              (funcall operation arg)
  2511.                (error))))
  2512.       (select-window wind)
  2513.                ))
  2514.  
  2515. (defun ediff-scroll-up (&optional arg)
  2516.   "Scroll up buffers A and B, if they are in windows.
  2517. With optional argument ARG, scroll ARG lines; otherwise scroll by nearly
  2518. the height of window-A."
  2519.   (interactive "P")
  2520.   (ediff-operate-on-windows
  2521.    'scroll-up 
  2522.    ;; calculate argument to scroll-up
  2523.    ;; if there is an explicit argument
  2524.    (if (and arg (not (equal arg '-)))
  2525.        ;; use it
  2526.        (prefix-numeric-value arg)
  2527.      ;; if not, see if we can determine a default amount (the window height)
  2528.      (let* ((window-A (get-buffer-window ediff-A-buffer t))
  2529.         (window-B (get-buffer-window ediff-B-buffer t))
  2530.         default-amount)
  2531.        (if (or (null window-A) (null window-B))
  2532.        (setq default-amount 0)
  2533.      (setq default-amount 
  2534.            (- (min (window-height window-A) (window-height window-B))
  2535.           1 next-screen-context-lines)))
  2536.        ;; the window was found
  2537.        (if arg
  2538.        ;; C-u as argument means half of default amount
  2539.        (/ default-amount 2)
  2540.      ;; no argument means default amount
  2541.      default-amount)))))
  2542.  
  2543. (defun ediff-scroll-down (&optional arg)
  2544.   "Scroll down buffers A and B, if they are in windows.
  2545. With optional argument ARG, scroll ARG lines; otherwise scroll by nearly
  2546. the height of window-A."
  2547.   (interactive "P")
  2548.   (ediff-operate-on-windows
  2549.    'scroll-down
  2550.    ;; calculate argument to scroll-down
  2551.    ;; if there is an explicit argument
  2552.    (if (and arg (not (equal arg '-)))
  2553.        ;; use it
  2554.        (prefix-numeric-value arg)
  2555.      ;; if not, see if we can determine a default amount (the window height)
  2556.      (let* ((window-A (get-buffer-window ediff-A-buffer t))
  2557.         (window-B (get-buffer-window ediff-B-buffer t))
  2558.         default-amount)
  2559.        (if (or (null window-A) (null window-B))
  2560.        (setq default-amount 0)
  2561.      (setq default-amount 
  2562.            (- (min (window-height window-A) (window-height window-B))
  2563.           1 next-screen-context-lines)))
  2564.        ;; the window was found
  2565.        (if arg
  2566.        ;; C-u as argument means half of default amount
  2567.        (/ default-amount 2)
  2568.      ;; no argument means default amount
  2569.      default-amount)))))
  2570.  
  2571. (defun ediff-scroll-left (&optional arg)
  2572.   "Scroll left buffer-A and buffer-B, if they are in windows.
  2573. If an argument is given, that is how many columns are scrolled, else nearly
  2574. the width of the A and B windows."
  2575.   (interactive "P")
  2576.   (ediff-operate-on-windows
  2577.    'scroll-left
  2578.    ;; calculate argument to scroll-left
  2579.    ;; if there is an explicit argument
  2580.    (if (and arg (not (equal arg '-)))
  2581.        ;; use it
  2582.        (prefix-numeric-value arg)
  2583.      ;; if not, see if we can determine a default amount
  2584.      ;; (half the window width)
  2585.      (if (null ediff-control-window)
  2586.      ;; no control window, use nil
  2587.      nil
  2588.        (let ((default-amount
  2589.            (- (/ (window-width ediff-control-window) 2) 3)))
  2590.      ;; the window was found
  2591.      (if arg
  2592.          ;; C-u as argument means half of default amount
  2593.          (/ default-amount 2)
  2594.        ;; no argument means default amount
  2595.        default-amount))))))
  2596.  
  2597. (defun ediff-scroll-right (&optional arg)
  2598.   "Scroll right buffer-A and buffer-B, if they are in windows.
  2599. If an argument is given, that is how many columns are scrolled, else nearly
  2600. the width of the A and B windows."
  2601.   (interactive "P")
  2602.   (ediff-operate-on-windows
  2603.    'scroll-right
  2604.    ;; calculate argument to scroll-right
  2605.    ;; if there is an explicit argument
  2606.    (if (and arg (not (equal arg '-)))
  2607.        ;; use it
  2608.        (prefix-numeric-value arg)
  2609.      ;; if not, see if we can determine a default amount
  2610.      ;; (half the window width)
  2611.      (if (null ediff-control-window)
  2612.      ;; no control window, use nil
  2613.      nil
  2614.        (let ((default-amount
  2615.            (- (/ (window-width ediff-control-window) 2) 3)))
  2616.      ;; the window was found
  2617.      (if arg
  2618.          ;; C-u as argument means half of default amount
  2619.          (/ default-amount 2)
  2620.        ;; no argument means default amount
  2621.        default-amount))))))
  2622.  
  2623. (defun ediff-position-region (beg end pos)
  2624.   "This is a variation on `emerge-position-region'. 
  2625. The difference is that it always tries to align difference regions in
  2626. buffer-A and buffer-B, so that it will be easier to compare them."
  2627.   (set-window-start (selected-window) beg)
  2628.   (if (pos-visible-in-window-p end)
  2629.       ;; Determine the number of lines that the region occupies
  2630.       (let ((lines 0))
  2631.     (while (> end (progn
  2632.             (move-to-window-line lines)
  2633.             (point)))
  2634.       (setq lines (1+ lines)))
  2635.     ;; And position the beginning on the right line
  2636.     (goto-char beg)
  2637.     (recenter (/ (1+ (max (- (1- (window-height (selected-window)))
  2638.                  lines)
  2639.                   1)
  2640.              )
  2641.              2))))
  2642.   (goto-char pos)
  2643.   )
  2644.  
  2645.  
  2646. (defun ediff-next-difference (&optional arg)
  2647.   "Advance to the next difference. 
  2648. With a prefix argument, go back that many differences."
  2649.   (interactive "P")
  2650.   (if (< ediff-current-difference ediff-number-of-differences)
  2651.       (let ((n (min ediff-number-of-differences
  2652.             (+ ediff-current-difference (if arg arg 1))))
  2653.         (buffer-read-only nil))
  2654.     (ediff-unselect-and-select-difference n))
  2655.     (error "At end of the difference list.")))
  2656.  
  2657. (defun ediff-previous-difference (&optional arg)
  2658.   "Go to the previous difference. 
  2659. With a prefix argument, go back that many differences."
  2660.   (interactive "P")
  2661.   (if (> ediff-current-difference -1)
  2662.       (let ((n (max -1 (- ediff-current-difference (if arg arg 1))))
  2663.         (buffer-read-only nil))
  2664.       (ediff-unselect-and-select-difference n))
  2665.     (error "At beginning of the difference list.")))
  2666.  
  2667. (defun ediff-jump-to-difference (difference-number)
  2668.   "Go to the difference specified as a prefix argument."
  2669.   (interactive "p")
  2670.   (let ((buffer-read-only nil))
  2671.     (setq difference-number (1- difference-number))
  2672.     (if (and (>= difference-number -1)
  2673.          (< difference-number (1+ ediff-number-of-differences)))
  2674.     (ediff-unselect-and-select-difference difference-number)
  2675.       (error "Bad difference number"))))
  2676.       
  2677. (defun ediff-jump-to-difference-at-point ()
  2678.   "Go to the difference closest to the point in buffer A or B.
  2679. If this command is invoked via `ja' or `ga' then the point in buffer A is
  2680. used. Otherwise, buffer B is used."
  2681.   (interactive)
  2682.   (let ((buffer-read-only nil)
  2683.     (buf-type (ediff-char-to-buftype last-command-char)))
  2684.     (ediff-jump-to-difference (ediff-diff-at-point buf-type))))
  2685.     
  2686.       
  2687. ;; find region "most related to the current point position      
  2688.  
  2689. (defun ediff-diff-at-point (buf-type)
  2690.   (let ((buffer (ediff-get-buffer buf-type))
  2691.     (ctl-buffer ediff-control-buffer)
  2692.     (diff-no -1)
  2693.     (prev-beg 0)
  2694.     (prev-end 0)
  2695.     (beg 0)
  2696.     (end 0))
  2697.     
  2698.     (emerge-eval-in-buffer
  2699.      buffer
  2700.      (while (or (< (point) prev-beg) (> (point) beg))
  2701.        (setq diff-no (1+ diff-no))
  2702.        (setq prev-beg beg
  2703.          prev-end end)
  2704.        (setq beg (ediff-get-diff-posn buf-type 'beg diff-no ctl-buffer)
  2705.          end (ediff-get-diff-posn buf-type 'end diff-no ctl-buffer))
  2706.        )
  2707.       
  2708.      (if (< (abs (- (point) prev-end))
  2709.         (abs (- (point) beg)))
  2710.      diff-no
  2711.        (1+ diff-no))  ;; jump-to-diff works with diff nums higher by 1
  2712.      )))
  2713.  
  2714. ;;; Copying diffs.
  2715.  
  2716. (defun ediff-diff-to-diff (arg)
  2717.   "Copy buffer-A'th diff to buffer B.
  2718. If numerical prefix argument, copy this diff specified in the arg.
  2719. Otherwise, copy the difference given by `ediff-current-difference'." 
  2720.   (interactive "P")
  2721.   (if arg
  2722.       (ediff-jump-to-difference arg))
  2723.   (ediff-copy-diff ediff-current-difference
  2724.            (ediff-char-to-buftype (aref (this-command-keys) 0))
  2725.            (ediff-char-to-buftype (aref (this-command-keys) 1)))
  2726.   (ediff-recenter 'no-rehighlight))
  2727.  
  2728.  
  2729. (defun ediff-copy-diff (n from-buf-type to-buf-type)
  2730.   "Copy diff N from FROM-BUF-TYPE \(given as 'A or 'B\) to TO-BUF-TYPE."
  2731.   (let* ((to-buf (ediff-get-buffer to-buf-type))
  2732.      (from-buf (ediff-get-buffer from-buf-type))
  2733.      (ctrl-buf ediff-control-buffer)
  2734.      reg-to-copy reg-to-delete
  2735.      reg-to-delete-beg reg-to-delete-end)
  2736.     
  2737.     (ediff-operate-on-flags 'remove)
  2738.     (setq reg-to-delete-beg
  2739.       (ediff-get-diff-posn to-buf-type 'beg n ctrl-buf))
  2740.     (setq reg-to-delete-end
  2741.       (ediff-get-diff-posn to-buf-type 'end n ctrl-buf))
  2742.     (setq reg-to-copy (emerge-eval-in-buffer
  2743.                from-buf
  2744.                (buffer-substring (ediff-get-diff-posn
  2745.                       from-buf-type 'beg n ctrl-buf)
  2746.                      (ediff-get-diff-posn
  2747.                       from-buf-type 'end n ctrl-buf))))
  2748.     (setq reg-to-delete (emerge-eval-in-buffer
  2749.              to-buf
  2750.              (buffer-substring reg-to-delete-beg
  2751.                        reg-to-delete-end)))
  2752.     (setq ediff-disturbed-overlays nil) ;; clear before use
  2753.     
  2754.     (if (string= reg-to-delete reg-to-copy)
  2755.     (progn
  2756.       (ding)
  2757.       (message
  2758.        "Diff regions %d are identical in buffers %S and %S. Nothing copied." 
  2759.        (1+ n) from-buf-type to-buf-type))
  2760.     
  2761.       ;; seems ok to copy
  2762.       (if (ediff-test-save-region n to-buf-type)
  2763.         (condition-case conds
  2764.         (let (inhibit-read-only)
  2765.           (emerge-eval-in-buffer
  2766.            to-buf
  2767.            ;; to prevent flags from interfering if buffer is writable
  2768.            (setq inhibit-read-only (null buffer-read-only))
  2769.            (let ((before-change-function nil))
  2770.              (goto-char reg-to-delete-end)
  2771.              (insert-before-markers reg-to-copy)
  2772.              (if (ediff-if-lucid)
  2773.              (progn
  2774.                (ediff-collect-extents-lucid reg-to-delete-beg)
  2775.                (if (> reg-to-delete-end reg-to-delete-beg)
  2776.                    (progn
  2777.                  (kill-region reg-to-delete-beg
  2778.                           reg-to-delete-end) 
  2779.                  (if (string= reg-to-copy "")
  2780.                      (ediff-adjust-disturbed-extents-lucid
  2781.                       reg-to-delete-beg)))))
  2782.                (if (> reg-to-delete-end reg-to-delete-beg)
  2783.                (kill-region reg-to-delete-beg reg-to-delete-end)
  2784.              (ediff-move-disturbed-overlays reg-to-delete-beg)))
  2785.              ))
  2786.           (ediff-save-diff-region n to-buf-type reg-to-delete))
  2787.           (error (message "%s %s"
  2788.                   (car conds)
  2789.                   (mapconcat 'prin1-to-string (cdr conds) " "))
  2790.              (beep 1))))
  2791.       )
  2792.     (ediff-operate-on-flags 'insert)
  2793.     ))
  2794.      
  2795. (defun ediff-save-diff-region (n buf-type reg)
  2796.   "Save Nth diff of buffer BUF-TYPE \(`A' or `B'\).
  2797. That is to say, the Nth diff on the `ediff-killed-diffs-alist'.  REG
  2798. is the region to save.  It is redundant here, but is passed anyway, for
  2799. convenience."
  2800.  
  2801.   (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
  2802.      (this-buf-n-th-diff-saved (assoc buf-type (cdr n-th-diff-saved))))
  2803.      
  2804.     (if this-buf-n-th-diff-saved
  2805.     ;; either nothing saved for n-th diff and buffer or we OK'ed
  2806.     ;; overriding
  2807.     (setcdr this-buf-n-th-diff-saved reg)
  2808.       (if n-th-diff-saved ;; n-th diff saved, but for another buffer
  2809.       (nconc n-th-diff-saved  (list (cons buf-type reg)))
  2810.     (setq ediff-killed-diffs-alist  ;; create record for n-th diff
  2811.           (cons (list n (cons buf-type reg))
  2812.             ediff-killed-diffs-alist))))
  2813.     (message "Saved diff region #%d for buffer %S. To recover hit 'r%s'."
  2814.          (1+ n) buf-type
  2815.          (downcase (symbol-name buf-type)))))
  2816.     
  2817. (defun ediff-test-save-region (n buf-type)
  2818.   "Test if saving Nth difference region of buffer BUF-TYPE is possible."
  2819.   (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
  2820.      (this-buf-n-th-diff-saved (assoc buf-type (cdr n-th-diff-saved))))
  2821.      
  2822.     (if this-buf-n-th-diff-saved
  2823.     (if (yes-or-no-p
  2824.          (format 
  2825.           "You've previously copied diff region %d to buffer %S. Confirm."
  2826.           (1+ n) buf-type))
  2827.         t
  2828.       (error "Quit."))
  2829.       t)))
  2830.       
  2831. (defun ediff-pop-diff (n buf-type)
  2832.   "Pop last killed Nth diff region from buffer BUF-TYPE."
  2833.   (let* ((n-th-record (assoc n ediff-killed-diffs-alist))
  2834.      (saved-rec (assoc buf-type (cdr n-th-record)))
  2835.      (buf (ediff-get-buffer buf-type))
  2836.      saved-diff reg-beg reg-end recovered)
  2837.     
  2838.     (if (cdr saved-rec)
  2839.     (setq saved-diff (cdr saved-rec))
  2840.       (if (> ediff-number-of-differences 0)
  2841.       (error "Nothing saved for diff %d in buffer %S." (1+ n) buf-type)
  2842.     (error "No differences found.")))
  2843.     
  2844.     (ediff-operate-on-flags 'remove)
  2845.     
  2846.     (setq reg-beg (ediff-get-diff-posn buf-type 'beg n ediff-control-buffer))
  2847.     (setq reg-end (ediff-get-diff-posn buf-type 'end n ediff-control-buffer))
  2848.     (setq ediff-disturbed-overlays nil) ;; clear before use
  2849.     
  2850.     (condition-case conds
  2851.     (emerge-eval-in-buffer
  2852.      buf
  2853.      (let ((inhibit-read-only (null buffer-read-only))
  2854.            (before-change-function nil))
  2855.        (goto-char reg-end)
  2856.        (insert-before-markers saved-diff)
  2857.        
  2858.        (if (ediff-if-lucid)
  2859.            (progn
  2860.          (ediff-collect-extents-lucid reg-beg)
  2861.          (if (> reg-end reg-beg)
  2862.              (progn
  2863.                (kill-region reg-beg reg-end)
  2864.                (if (string= saved-diff "")
  2865.                (ediff-adjust-disturbed-extents-lucid reg-beg)))))
  2866.          (if (> reg-end reg-beg)
  2867.          (kill-region reg-beg reg-end)
  2868.            (ediff-move-disturbed-overlays reg-beg)))
  2869.          
  2870.        (setq recovered t)
  2871.        ))
  2872.       (error (message "%s %s"
  2873.               (car conds)
  2874.               (mapconcat 'prin1-to-string (cdr conds) " "))
  2875.          (beep 1)))
  2876.     
  2877.     (ediff-operate-on-flags 'insert)
  2878.     (if recovered
  2879.     (progn
  2880.       (setq  n-th-record (delq saved-rec n-th-record))
  2881.       (message "Restored diff region %d in buffer %S." (1+ n) buf-type)))
  2882.     ))
  2883.       
  2884. (defun ediff-restore-diff  (arg)
  2885.   "Restore ARGth diff from `ediff-killed-diffs-alist'.
  2886. ARG is a prefix argument.  If ARG is nil, restore current-difference."
  2887.   (interactive "P")
  2888.   (if arg
  2889.       (ediff-jump-to-difference arg))
  2890.   (ediff-pop-diff ediff-current-difference 
  2891.           (ediff-char-to-buftype last-command-char))
  2892.   (ediff-recenter 'no-rehighlight))
  2893.     
  2894.  
  2895. ;;; Quitting, suspending, etc.
  2896. (defun ediff-quit ()
  2897.   "Finish an Ediff session and exit Ediff.
  2898. Unselects the selected difference, if any, restores the read-only and modified
  2899. flags of the compared file buffers, kills Ediff buffers for this session
  2900. \(but not file-A and file-B\)."
  2901.   (interactive)
  2902.   (if (prog1
  2903.       (y-or-n-p "Do you really want to exit Ediff? ")
  2904.     (message ""))
  2905.       (ediff-really-quit)))
  2906.  
  2907.  
  2908. ;; Perform the quit operations.
  2909. (defun ediff-really-quit ()
  2910.   (setq ediff-help-message ediff-help-message-long)
  2911.   (ediff-restore-buffer-characteristics t) ;; restore as they were at setup
  2912.   (ediff-unhighlight-diffs-totally)
  2913.   (ediff-clear-diff-vector ediff-difference-vector 'fine-diffs-also)
  2914.   (if ediff-temp-file-A (delete-file ediff-temp-file-A))
  2915.   (if ediff-temp-file-B (delete-file ediff-temp-file-B))
  2916.   
  2917.   ;; restore buffer mode line id's in buffer-A/B
  2918.   (let ((control-buffer ediff-control-buffer))
  2919.     (emerge-eval-in-buffer
  2920.      ediff-A-buffer
  2921.      (setq before-change-function nil)
  2922.      (setq ediff-this-buffer-control-sessions 
  2923.        (delq control-buffer ediff-this-buffer-control-sessions))
  2924.      (if (null ediff-this-buffer-control-sessions)
  2925.      (setq local-write-file-hooks 
  2926.            (delq 'ediff-block-write-file local-write-file-hooks)))
  2927.      (kill-local-variable 'mode-line-buffer-identification))
  2928.     (emerge-eval-in-buffer
  2929.      ediff-B-buffer
  2930.      (setq ediff-this-buffer-control-sessions 
  2931.        (delq control-buffer ediff-this-buffer-control-sessions))
  2932.      (if (null ediff-this-buffer-control-sessions)
  2933.      (setq local-write-file-hooks 
  2934.            (delq 'ediff-block-write-file local-write-file-hooks)))
  2935.      (setq before-change-function nil)
  2936.      (kill-local-variable 'mode-line-buffer-identification)))
  2937.    
  2938.   (run-hooks 'ediff-quit-hooks))
  2939.   
  2940. (defun ediff-kill-buffer-carefully (buf)
  2941.   "Kill buffer BUF if it exists."
  2942.   (if (ediff-buffer-live-p buf)
  2943.       (kill-buffer (get-buffer buf))))
  2944.  
  2945. ;; The default way of quitting Ediff.
  2946. ;; Kills control buffers and leaves the
  2947. ;; frame split between the two diff'ed files.
  2948. (defun ediff-default-quit-hook ()
  2949.   (let ((buff-A ediff-A-buffer)
  2950.     (buff-B ediff-B-buffer))
  2951.     (ediff-kill-buffer-carefully ediff-diff-buffer)
  2952.     (ediff-kill-buffer-carefully ediff-tmp-buffer)
  2953.     (ediff-kill-buffer-carefully ediff-error-buffer)
  2954.     (ediff-kill-buffer-carefully ediff-control-buffer)
  2955.     (ediff-kill-buffer-carefully ediff-patch-diagnostics)
  2956.     (delete-other-windows)
  2957.     (switch-to-buffer buff-B)
  2958.     (split-window-vertically)
  2959.     (switch-to-buffer buff-A)))
  2960.     
  2961. ;; The default way of suspending Ediff.
  2962. ;; Buries Ediff buffers, kills all windows.
  2963. (defun ediff-default-suspend-hook ()
  2964.   (let ((buf-A ediff-A-buffer)
  2965.     (buf-B ediff-B-buffer)
  2966.     (buf-patch ediff-patch-buf)
  2967.     (buf-patch-diag ediff-patch-diagnostics)
  2968.     (buf-err  ediff-error-buffer)
  2969.     (buf-diff ediff-diff-buffer))
  2970.     (bury-buffer) ;; ediff-control-buffer
  2971.     (delete-other-windows)
  2972.     (bury-buffer buf-err)
  2973.     (bury-buffer buf-diff)
  2974.     (bury-buffer buf-patch)
  2975.     (bury-buffer buf-patch-diag)
  2976.     (bury-buffer buf-A)
  2977.     (bury-buffer buf-B)))
  2978.      
  2979.      
  2980. (defun ediff-suspend ()
  2981.   "Suspend Ediff.
  2982. To resume, switch to the appropriate `*ediff-control*'
  2983. buffer and then type \\[ediff-recenter].  Ediff will automatically set
  2984. up an appropriate window config."
  2985.   (interactive)
  2986.   (let ((key (substitute-command-keys "\\[ediff-recenter]")))
  2987.   (run-hooks 'ediff-suspend-hooks)
  2988.   (message
  2989.    "To resume Ediff, switch to *ediff-control* and hit '%S'" key)))
  2990.  
  2991.  
  2992. (defun ediff-file-names ()
  2993.   "Show the names of the buffers or files being operated on by Ediff.
  2994. Hit \\[ediff-recenter] to reset the windows afterward."
  2995.   (interactive)
  2996.   (with-output-to-temp-buffer "*Help*"
  2997.     (emerge-eval-in-buffer ediff-A-buffer
  2998.                (if buffer-file-name
  2999.                    (princ
  3000.                 (format "File A is: %s\n" buffer-file-name))
  3001.                  (princ 
  3002.                   (format "Buffer A is: %s\n" (buffer-name)))))
  3003.     (emerge-eval-in-buffer ediff-B-buffer
  3004.                (if buffer-file-name
  3005.                    (princ
  3006.                 (format "File B is: %s\n" buffer-file-name))
  3007.                  (princ 
  3008.                   (format "Buffer B is: %s\n" (buffer-name)))))
  3009.     ))
  3010.  
  3011.  
  3012.  
  3013. (defun ediff-line-numbers ()
  3014.   "Display the current line numbers.
  3015. This function displays the line numbers of the points in the A, B."
  3016.   (interactive)
  3017.   (let* ((A-line (emerge-eval-in-buffer ediff-A-buffer
  3018.                        (count-lines (point-min) (point))))
  3019.      (B-line (emerge-eval-in-buffer ediff-B-buffer
  3020.                        (count-lines (point-min) (point)))))
  3021.     (message "At lines:  A = %d, B = %d" A-line B-line)))
  3022.  
  3023.  
  3024. ;;; Support routines
  3025.  
  3026. ;; Select a difference by placing the ASCII flags around the appropriate
  3027. ;; group of lines in the A, B buffers
  3028. (defun ediff-select-difference (n)
  3029.   (if (and (>= n 0) (< n ediff-number-of-differences))
  3030.       (progn
  3031.     (ediff-remember-buffer-characteristics)
  3032.     (if (and window-system ediff-want-faces)
  3033.         (progn
  3034.           (ediff-highlight-diff n)
  3035.           (setq ediff-highlighting-style 'face))
  3036.       (setq ediff-highlighting-style 'ascii)
  3037.       (ediff-place-flags-in-buffer 'A ediff-A-buffer
  3038.                        ediff-control-buffer n)
  3039.       (ediff-place-flags-in-buffer 'B ediff-B-buffer
  3040.                        ediff-control-buffer n)) 
  3041.       
  3042.     (if window-system
  3043.         (cond ((eq ediff-auto-refine 'on)
  3044.            (if (and
  3045.             (> ediff-auto-refine-limit
  3046.                (- (ediff-get-diff-posn 'A 'end n)
  3047.                   (ediff-get-diff-posn 'A 'beg n)))
  3048.             (> ediff-auto-refine-limit
  3049.                (- (ediff-get-diff-posn 'B 'end n)
  3050.                   (ediff-get-diff-posn 'B 'beg n))))
  3051.                (ediff-make-fine-diffs n 'noforce)
  3052.              (ediff-make-fine-diffs n 'skip)))
  3053.           
  3054.           ((eq ediff-auto-refine 'off)       ; highlight iff fine diffs
  3055.            (ediff-make-fine-diffs n 'skip)))) ; already exist 
  3056.      
  3057.     (ediff-restore-buffer-characteristics)
  3058.     (run-hooks 'ediff-select-hooks))))
  3059.     
  3060.  
  3061. ;; Unselect a difference by removing the ASCII flags in the buffers.
  3062. (defun ediff-unselect-difference (n)
  3063.   (if (and (>= n 0) (< n ediff-number-of-differences))
  3064.       (progn 
  3065.     (ediff-remember-buffer-characteristics)
  3066.     
  3067.     (cond ((and window-system ediff-want-faces)
  3068.            (ediff-unhighlight-diff))
  3069.           ((eq ediff-highlighting-style 'ascii)
  3070.            (ediff-remove-flags-from-buffer
  3071.         ediff-A-buffer
  3072.         (ediff-get-diff-posn 'A 'beg n)
  3073.         (ediff-get-diff-posn 'A 'end n)
  3074.         ediff-before-flag-A ediff-after-flag-A)
  3075.            (ediff-remove-flags-from-buffer
  3076.         ediff-B-buffer
  3077.         (ediff-get-diff-posn 'B 'beg n)
  3078.         (ediff-get-diff-posn 'B 'end n)
  3079.         ediff-before-flag-B ediff-after-flag-B)))
  3080.         
  3081.     (ediff-restore-buffer-characteristics)
  3082.     (setq ediff-highlighting-style nil)
  3083.     
  3084.     ;; unhighlight fine diffs
  3085.     (if window-system
  3086.         (ediff-set-fine-diff-properties
  3087.          ediff-current-difference 'default))
  3088.     
  3089.     (run-hooks 'ediff-unselect-hooks))))
  3090.   
  3091.  
  3092. ;; Unselects prev diff and selects a new one, if FLAG has value other than
  3093. ;; 'select-only or 'unselect-only.  If FLAG is 'select-only, the
  3094. ;; next difference is selected, but the current selection is not
  3095. ;; unselected.  If FLAG is 'unselect-only then the current selection is
  3096. ;; unselected, but the next one is not selected.  If NO-RECENTER is non-nil,
  3097. ;; don't recenter buffers after selecting/unselecting.
  3098. ;; 
  3099. ;; Don't use `ediff-select-difference' and `ediff-unselect-difference'
  3100. ;; directly,;; since this will screw up the undo info in the presence of
  3101. ;; ASCII flags. 
  3102. ;; Instead, use `ediff-unselect-and-select-difference' with appropriate
  3103. ;; flags.
  3104.  
  3105. (defun ediff-unselect-and-select-difference (n &optional flag no-recenter)
  3106.   (let (;; save buf modified info
  3107.     (control-buf ediff-control-buffer)
  3108.     (buf-A-modified (buffer-modified-p ediff-A-buffer))
  3109.     (buf-B-modified (buffer-modified-p ediff-B-buffer))
  3110.     ;; temporarily disable undo so highlighting won't confuse the user
  3111.     buf-A-undo buf-B-undo)
  3112.     
  3113.     (let ((ediff-current-difference n))
  3114.       (or no-recenter
  3115.       (ediff-recenter 'no-rehighlight)))
  3116.       
  3117.     (emerge-eval-in-buffer
  3118.      ediff-A-buffer
  3119.      (setq buf-A-undo buffer-undo-list))
  3120.     (emerge-eval-in-buffer
  3121.      ediff-B-buffer
  3122.      (setq buf-B-undo buffer-undo-list))
  3123.     
  3124.     (buffer-disable-undo ediff-A-buffer)
  3125.     (buffer-disable-undo ediff-B-buffer)
  3126.     
  3127.     (unwind-protect    ;; we don't want to lose undo info due to error
  3128.     (progn
  3129.       (or (eq flag 'select-only)
  3130.           (ediff-unselect-difference ediff-current-difference))
  3131.       
  3132.       ;; Auto-save buffers while Ediff flags are temporarily removed.
  3133.       (emerge-eval-in-buffer
  3134.        ediff-A-buffer
  3135.        (if buf-A-modified
  3136.            (do-auto-save)))
  3137.       (emerge-eval-in-buffer
  3138.        ediff-B-buffer
  3139.        (if buf-B-modified
  3140.            (do-auto-save)))
  3141.       
  3142.       (or (eq flag 'unselect-only)
  3143.           (ediff-select-difference n))
  3144.       (setq ediff-current-difference n)
  3145.       ) ;; end protected section
  3146.       
  3147.       (emerge-eval-in-buffer
  3148.        control-buf
  3149.       (ediff-refresh-mode-line)
  3150.       
  3151.       ;; restore undo and buffer-modified info
  3152.       (emerge-eval-in-buffer
  3153.        ediff-A-buffer
  3154.        (set-buffer-modified-p buf-A-modified)
  3155.        (setq buffer-undo-list buf-A-undo)))
  3156.        
  3157.       (emerge-eval-in-buffer
  3158.        control-buf
  3159.       (emerge-eval-in-buffer
  3160.        ediff-B-buffer
  3161.        (set-buffer-modified-p buf-B-modified)
  3162.        (setq buffer-undo-list buf-B-undo))
  3163.       ))))
  3164.  
  3165. ;; Revise the mode line to display which difference we have selected
  3166.  
  3167. (defun ediff-refresh-mode-line ()
  3168.   (setq mode-line-buffer-identification
  3169.     (cond ((< ediff-current-difference 0)
  3170.            (list (format "Ediff: %%b  At start: %d diffs"
  3171.                  ediff-number-of-differences)))
  3172.           ((>= ediff-current-difference ediff-number-of-differences)
  3173.            (list (format "Ediff: %%b  At end: %d diffs"
  3174.                  ediff-number-of-differences)))
  3175.           (t
  3176.            (list (format "Ediff: %%b   diff %d of %d"
  3177.                  (1+ ediff-current-difference)
  3178.                  ediff-number-of-differences)))))
  3179.   ;; Force mode-line redisplay
  3180.   (set-buffer-modified-p (buffer-modified-p)))
  3181.  
  3182.  
  3183.  
  3184. ;; Verify that we have a difference selected.
  3185. (defun ediff-validate-difference ()
  3186.   (if (not (and (>= ediff-current-difference 0)
  3187.         (< ediff-current-difference ediff-number-of-differences)))
  3188.       (error "No difference selected")))
  3189.  
  3190. (defun ediff-read-file-name (prompt default-dir default-file A-file)
  3191. ; This is a modified version of a similar function in `emerge.el'.
  3192. ; PROMPT should not have trailing ': ', so that it can be modified
  3193. ; according to context.
  3194. ; If both A-FILE and default-dir are set, the file constructed our of
  3195. ; default-dir and the non-directory part of A-FILE is used as default and as
  3196. ; initial input.
  3197. ; If A-FILE is set (but default-dir is not), it is used as default and
  3198. ; initial input. 
  3199. ; If default-file is set, it should be used as the default value.
  3200. ; If default-dir is non-nil, use it as the default directory.
  3201. ; Otherwise, use the value in Emacs's var default-directory.
  3202.   (let (f)
  3203.     (setq f
  3204.       (cond
  3205.        ((and A-file default-dir)
  3206.         (read-file-name (format "%s (default %s%s): "
  3207.                     prompt
  3208.                     (abbreviate-file-name
  3209.                      (expand-file-name default-dir))
  3210.                     (file-name-nondirectory A-file))
  3211.                 (expand-file-name default-dir)
  3212.                 (concat (expand-file-name default-dir)
  3213.                     (file-name-nondirectory A-file))
  3214.                 'confirm (file-name-nondirectory A-file)))
  3215.        (A-file
  3216.         (read-file-name (format "%s (default %s): "
  3217.                     prompt (file-name-nondirectory A-file))
  3218.                 (expand-file-name (file-name-directory A-file))
  3219.                 A-file
  3220.                 'confirm (file-name-nondirectory A-file)))
  3221.        ;; If there is a default file, but no A-file, use it.
  3222.        (default-file
  3223.          (read-file-name (format "%s (default %s): " prompt default-file)
  3224.                  default-dir;; if nil then default-directory.
  3225.                  nil 'confirm))
  3226.        (t
  3227.         (read-file-name (concat prompt ": ")
  3228.                 default-dir;; if nil then default-directory.
  3229.                 nil 'confirm))))
  3230.     ;; If user enters a directory name, expand the default file in that
  3231.     ;; directory.  This allows the user to enter a directory name for the
  3232.     ;; B-file and diff against the A-file in that directory instead of a DIRED
  3233.     ;; listing!
  3234.     (if (and (file-directory-p f)
  3235.          (or A-file default-file))
  3236.     (setq f (expand-file-name
  3237.          (file-name-nondirectory (or A-file default-file)) f)))
  3238.     f))
  3239.  
  3240.   
  3241. ;; If `prefix' is given, then it is used as a prefix for the temp file
  3242. ;; name. Otherwise, `.buffer-name' is used. If `file' is given, use this
  3243. ;; file and don't create a new one.
  3244. (defun ediff-make-temp-file (&optional prefix given-file)
  3245.   (let ((f (or given-file
  3246.            (make-temp-name (concat
  3247.                 ediff-temp-file-prefix
  3248.                 (or prefix
  3249.                     (format
  3250.                      ".%s"
  3251.                      (file-name-nondirectory
  3252.                       (buffer-name))))))))) 
  3253.     ;; create the file
  3254.     (write-region (point-min) (point-max) f nil 'no-message) 
  3255.     (set-file-modes f ediff-temp-file-mode)
  3256.     f))
  3257.  
  3258. ;; Quote metacharacters (using \) when executing diff in Unix, but not in
  3259. ;; EMX OS/2
  3260. (defun ediff-protect-metachars (str)
  3261.   (or (eq system-type 'emx)
  3262.       (let ((limit 0))
  3263.     (while (string-match emerge-metachars str limit)
  3264.       (setq str (concat (substring str 0 (match-beginning 0))
  3265.               "\\"
  3266.               (substring str (match-beginning 0))))
  3267.       (setq limit (1+ (match-end 0))))))
  3268.   str)
  3269.  
  3270.  
  3271. (defun ediff-block-write-file ()    
  3272.   "Prevent writing files A and B directly."
  3273.   (if (ediff-check-for-ascii-flags)
  3274.       (error "Use 'wa' and 'wb' to save buffs A/B (first switch back to *ediff-control*.")))
  3275.  
  3276. (defun ediff-check-for-ascii-flags ()
  3277.   (eval
  3278.    (cons 'or
  3279.      (mapcar (function (lambda (buf)
  3280.                  (emerge-eval-in-buffer
  3281.                   buf
  3282.                   (eq ediff-highlighting-style 'ascii))))
  3283.          ediff-this-buffer-control-sessions))))
  3284.  
  3285. (defun ediff-insert-in-front (overl beg end)
  3286.   "Capture overlays that had insertions in the front.
  3287. Called when overlay OVERL gets insertion in front."
  3288.   (if (ediff-overlay-get overl 'ediff-diff-num)
  3289.       (setq ediff-disturbed-overlays
  3290.         (cons overl ediff-disturbed-overlays)))
  3291.   )
  3292.   
  3293. (defun ediff-collect-extents-lucid (pos)
  3294.   "Collects all extents at POS having property `ediff-diff-num'.
  3295. Lucid Emacs causes headache by detaching empty extents, so I have to save
  3296. them before they disappear."
  3297.   (let (lis elt)
  3298.     (while (setq elt (extent-at pos nil 'ediff-diff-num elt))
  3299.       (setq lis (cons elt lis)))
  3300.     (setq ediff-disturbed-overlays lis)))
  3301.   
  3302. (defun ediff-move-disturbed-overlays (posn)  
  3303.   (mapcar (function (lambda (overl)
  3304.                (ediff-move-overlay overl
  3305.                        posn
  3306.                        (ediff-overlay-end overl))
  3307.                ))
  3308.       ediff-disturbed-overlays)
  3309.   (setq ediff-disturbed-overlays nil))
  3310.   
  3311. (defun ediff-adjust-disturbed-extents-lucid (posn &optional posn-type)
  3312. ;; POSN-TYPE tells if POSN should become a new start of the extents
  3313. ;; (if 'new-start) or a new end (if 'new-end). If POSN-TYPE is nil, then
  3314. ;; POSN is both the new start and the new end.
  3315.   (mapcar (function (lambda (overl)
  3316.                (cond ((and (null posn-type)
  3317.                    (equal (ediff-overlay-start overl)
  3318.                       (ediff-overlay-end overl)))
  3319.                   (ediff-move-overlay overl posn posn))
  3320.                
  3321.                  (posn-type
  3322.                   (ediff-move-overlay
  3323.                    overl
  3324.                    (if (eq posn-type 'new-start)
  3325.                    posn
  3326.                  (ediff-overlay-start overl))
  3327.                    (if (eq posn-type 'new-end)
  3328.                    posn
  3329.                  (ediff-overlay-end overl)))))))
  3330.       ediff-disturbed-overlays)
  3331.     (setq ediff-disturbed-overlays nil))
  3332.   
  3333. (defun ediff-save-buffer ()
  3334.   "Safe way of saving buffers A and B."
  3335.   (interactive)
  3336.   (let ((hooks local-write-file-hooks))
  3337.     (ediff-unselect-and-select-difference ediff-current-difference
  3338.                       'unselect-only)
  3339.     (unwind-protect
  3340.     (emerge-eval-in-buffer
  3341.      (if (eq last-command-char ?a) ediff-A-buffer ediff-B-buffer)
  3342.      ;; temporarily remove writing block 
  3343.      (setq hooks (delq 'ediff-block-write-file hooks))
  3344.      (let ((local-write-file-hooks hooks))
  3345.        (save-buffer)))
  3346.       (ediff-unselect-and-select-difference ediff-current-difference
  3347.                         'select-only)
  3348.       )))
  3349.     
  3350.  
  3351.        
  3352. ;; Essentially `emerge-remove-flags-in-buffer', modified to allow deletion
  3353. ;; of read-only flags.
  3354. (defun ediff-remove-flags-from-buffer (buffer before-posn after-posn
  3355.                           before-flag after-flag)
  3356.   (emerge-eval-in-buffer
  3357.    buffer
  3358.    (let ((buffer-read-only nil)
  3359.      (before-change-function nil)
  3360.      (inhibit-read-only t)
  3361.      (before-flag-length (length before-flag))
  3362.      (after-flag-length (length after-flag))
  3363.      )
  3364.      (goto-char after-posn)
  3365.      (setq after-posn (point-marker)) ;; after-posn is now a marker
  3366.      ;; remove the flags, if they're there
  3367.      (goto-char (- before-posn before-flag-length))
  3368.      (if (ediff-if-lucid)
  3369.      (ediff-collect-extents-lucid (+ (point) before-flag-length)))
  3370.      (if (looking-at (regexp-quote before-flag))
  3371.      (delete-region (point) (+ (point) before-flag-length))
  3372.        ;; the flag isn't there
  3373.        (ding)
  3374.        (message "Trouble removing ASCII flag"))
  3375.      (if (ediff-if-lucid)
  3376.      (ediff-adjust-disturbed-extents-lucid (point)))
  3377.      
  3378.      (if (ediff-if-lucid)
  3379.      (ediff-collect-extents-lucid (point)))
  3380.      (goto-char after-posn)
  3381.      (if (looking-at (regexp-quote after-flag))
  3382.      (delete-region (point) (+ (point) after-flag-length))
  3383.        ;; the flag isn't there
  3384.        (ding)
  3385.        (message "Trouble removing ASCII flag"))
  3386.      (if (ediff-if-lucid)
  3387.      (ediff-adjust-disturbed-extents-lucid (point)))
  3388.      (setq after-posn nil) ;; after has become a marker--garbage-collect
  3389.      )))
  3390.  
  3391.  
  3392. ;; This is a modified `emerge-place-flags-in-buffer'.
  3393. (defun ediff-place-flags-in-buffer (buf-type buffer ctl-buffer difference)
  3394.   (emerge-eval-in-buffer
  3395.    buffer
  3396.    (ediff-place-flags-in-buffer1 buf-type ctl-buffer difference)))
  3397.  
  3398. ;; Modified `emerge-place-flags-in-buffer1'.
  3399. (defun ediff-place-flags-in-buffer1 (buf-type ctl-buffer difference)
  3400.   (let ((buffer-read-only nil)
  3401.     (inhibit-read-only t)
  3402.     (before-change-function nil)
  3403.     (before-flag-name (if (eq buf-type 'A)
  3404.                    'ediff-before-flag-A
  3405.                 'ediff-before-flag-B))
  3406.     (after-flag-name (if (eq buf-type 'A)
  3407.                    'ediff-after-flag-A
  3408.                  'ediff-after-flag-B))
  3409.     beg-of-line flag)
  3410.     
  3411.     ;; insert the flag before the difference
  3412.     (let ((before (ediff-get-diff-posn buf-type 'beg difference ctl-buffer)))
  3413.       (goto-char before)
  3414.       (setq beg-of-line (bolp))
  3415.       
  3416.       (setq flag (emerge-eval-in-buffer
  3417.           ctl-buffer
  3418.           (if beg-of-line
  3419.               (set before-flag-name ediff-before-flag-bol)
  3420.             (set before-flag-name ediff-before-flag-mol))))
  3421.      
  3422.       ;; insert the flag itself
  3423.       (if (ediff-if-lucid)
  3424.       (ediff-collect-extents-lucid (point)))
  3425.       (insert-before-markers flag)
  3426.       (if (ediff-if-lucid)
  3427.       ;; Lucid's extent end-points behave strangely; they won't
  3428.       ;; respect insert-before-markers
  3429.       (ediff-adjust-disturbed-extents-lucid (point) 'new-start))
  3430.       )
  3431.     ;; insert the flag after the difference
  3432.     (let* ((after (ediff-get-diff-posn buf-type 'end difference ctl-buffer)))
  3433.       (goto-char after)
  3434.       (setq beg-of-line (bolp))
  3435.  
  3436.       (setq flag (emerge-eval-in-buffer
  3437.           ctl-buffer
  3438.           (if beg-of-line
  3439.               (set after-flag-name ediff-after-flag-bol)
  3440.             (set after-flag-name ediff-after-flag-mol))))
  3441.  
  3442.       ;; insert the flag itself
  3443.       (if (ediff-if-lucid)
  3444.       (ediff-collect-extents-lucid (point)))
  3445.       (insert flag)
  3446.       (if (ediff-if-lucid)
  3447.       (ediff-adjust-disturbed-extents-lucid after 'new-end))
  3448.       )))
  3449.  
  3450.   
  3451. (defun ediff-get-diff-posn (buf-type pos &optional n control-buf)
  3452.   "Returns positions of difference sectors in the BUF-TYPE buffer.
  3453. BUF-TYPE should be a symbol--either `A' or `B'. 
  3454. POS is either `beg' or `end'--it specifies whether you want the position at the
  3455. beginning of a difference or at the end.
  3456.  
  3457. The optional argument N says which difference \(default:
  3458. `ediff-current-difference'\).  The optional argument CONTROL-BUF says
  3459. which control buffer is in effect in case it is not the current
  3460. buffer."
  3461.   (let (diff-overlay)
  3462.     (or control-buf
  3463.     (setq control-buf (current-buffer)))
  3464.  
  3465.     (emerge-eval-in-buffer
  3466.      control-buf
  3467.      (or n  (setq n ediff-current-difference))
  3468.      (if (or (< n 0) (>= n ediff-number-of-differences))
  3469.      (if (> ediff-number-of-differences 0)
  3470.          (error "There is no diff %d. Valid diffs are 1 to %d."
  3471.             (1+ n) ediff-number-of-differences)
  3472.        (error "No differences found.")))
  3473.      (setq diff-overlay (ediff-get-diff-overlay n buf-type)))
  3474.      
  3475.     (if (ediff-overlay-get diff-overlay 'detached)
  3476.     (ediff-move-overlay diff-overlay
  3477.                 (ediff-overlay-get diff-overlay 'ediff-marker)
  3478.                 (ediff-overlay-get diff-overlay 'ediff-marker)))
  3479.     (if (eq pos 'beg)
  3480.     (ediff-overlay-start diff-overlay)
  3481.       (ediff-overlay-end diff-overlay))
  3482.     ))
  3483.     
  3484.  
  3485.  
  3486. ;; These would highlight differences under X
  3487. (defun ediff-highlight-diff (n)
  3488.   "Put face on diff N.  Invoked for X displays only."
  3489.   (let* ((last-A (emerge-eval-in-buffer ediff-A-buffer (point-max)))
  3490.      (last-B (emerge-eval-in-buffer ediff-B-buffer (point-max)))
  3491.      (begin-A (ediff-get-diff-posn 'A 'beg n))
  3492.      (end-A (ediff-get-diff-posn 'A 'end n))
  3493.      (xtraA (if (equal begin-A end-A) 1 0))
  3494.      (end-A-hilit (min last-A (+ end-A xtraA)))
  3495.      
  3496.      (begin-B (ediff-get-diff-posn 'B 'beg n))
  3497.      (end-B (ediff-get-diff-posn 'B 'end n))
  3498.      (xtraB (if (equal begin-B end-B) 1 0))
  3499.      (end-B-hilit (min last-B (+ end-B xtraB))))
  3500.       
  3501.     (if (ediff-if-lucid)
  3502.     (progn 
  3503.       (ediff-move-overlay
  3504.        ediff-current-diff-overlay-A begin-A end-A-hilit)
  3505.       (ediff-move-overlay
  3506.        ediff-current-diff-overlay-B begin-B end-B-hilit))
  3507.       ;; Emacs 19.22 has a bug, which requires that ediff-move-overlay will
  3508.       ;; have the buffer as a parameter.  Believed fixed in 19.23.
  3509.       (ediff-move-overlay ediff-current-diff-overlay-A
  3510.               begin-A end-A-hilit ediff-A-buffer)
  3511.       (ediff-move-overlay ediff-current-diff-overlay-B
  3512.               begin-B end-B-hilit ediff-B-buffer))
  3513.     ;; giving priority of 0 and then changing it may look funny, but
  3514.     ;; this is intended to overcome an Emacs bug.
  3515.     (ediff-overlay-put ediff-current-diff-overlay-A 'priority  0)
  3516.     (ediff-overlay-put ediff-current-diff-overlay-B 'priority  0)
  3517.     (ediff-overlay-put ediff-current-diff-overlay-A 'priority  
  3518.          (ediff-highest-priority begin-A end-A-hilit ediff-A-buffer))
  3519.     (ediff-overlay-put ediff-current-diff-overlay-B 'priority 
  3520.          (ediff-highest-priority begin-B end-B-hilit ediff-B-buffer))
  3521.          
  3522.     (or (face-differs-from-default-p 'ediff-odd-diff-face-A-var)
  3523.     (not ediff-highlight-all-diffs)
  3524.     (progn
  3525.       (copy-face ediff-odd-diff-face-A 'ediff-odd-diff-face-A-var)
  3526.       (copy-face ediff-odd-diff-face-B 'ediff-odd-diff-face-B-var)
  3527.       (copy-face ediff-even-diff-face-A 'ediff-even-diff-face-A-var)
  3528.       (copy-face ediff-even-diff-face-B 'ediff-even-diff-face-B-var)))
  3529.       
  3530.     ;; unhighlight the background overlay for the diff n so they won't
  3531.     ;; interfere with the current diff overlay
  3532.     (ediff-overlay-put (ediff-get-diff-overlay n 'A) 'face nil)
  3533.     (ediff-overlay-put (ediff-get-diff-overlay n 'B) 'face nil)
  3534.     
  3535.     (sit-for 0) ;; needs to synch for some reason
  3536.     ))
  3537.  
  3538.  
  3539. (defun ediff-unhighlight-diff ()
  3540.   "Remove overlays from buffers A and B."
  3541.     
  3542.   (ediff-move-overlay ediff-current-diff-overlay-A 1 1)
  3543.   (ediff-move-overlay ediff-current-diff-overlay-B 1 1)
  3544.   
  3545.   ;; rehighlight the overlay in the background of the
  3546.   ;; current difference region
  3547.   (ediff-overlay-put (ediff-get-diff-overlay ediff-current-difference 'A)
  3548.              'face (if (ediff-odd-p ediff-current-difference)
  3549.                    'ediff-odd-diff-face-A-var
  3550.                  'ediff-even-diff-face-A-var))
  3551.   (ediff-overlay-put (ediff-get-diff-overlay ediff-current-difference 'B)
  3552.              'face (if (ediff-odd-p ediff-current-difference)
  3553.                    'ediff-odd-diff-face-B-var
  3554.                  'ediff-even-diff-face-B-var))
  3555.   )
  3556.  
  3557.  
  3558. ;; delete highlighting overlays, restore faces to their original form
  3559. (defun ediff-unhighlight-diffs-totally ()
  3560.     (setq buffer-read-only nil)
  3561.     (ediff-unselect-and-select-difference -1)
  3562.     
  3563.     (if (and window-system ediff-want-faces)
  3564.     (let ((inhibit-quit t))
  3565.       (if (face-differs-from-default-p 'ediff-odd-diff-face-A-var)
  3566.           (progn
  3567.         (copy-face 'default 'ediff-odd-diff-face-A-var)
  3568.         (copy-face 'default 'ediff-odd-diff-face-B-var)
  3569.         (copy-face 'default 'ediff-even-diff-face-A-var)
  3570.         (copy-face 'default 'ediff-even-diff-face-B-var)))
  3571.       (if (ediff-overlayp ediff-current-diff-overlay-A)
  3572.           (ediff-delete-overlay ediff-current-diff-overlay-A))
  3573.       (setq ediff-current-diff-overlay-A nil)
  3574.       (if (ediff-overlayp ediff-current-diff-overlay-B)
  3575.           (ediff-delete-overlay ediff-current-diff-overlay-B))
  3576.       (setq ediff-current-diff-overlay-B nil)))
  3577.     )
  3578.     
  3579. (defun ediff-clear-diff-vector (vec &optional fin-diffs-also)
  3580.   ;; null out the difference overlays so they won't slow down future
  3581.   ;; editing operations
  3582.   (mapcar (function
  3583.        (lambda (elt)
  3584.          (ediff-delete-overlay (ediff-get-diff-overlay-from-vector elt 'A))
  3585.          (ediff-delete-overlay (ediff-get-diff-overlay-from-vector elt 'B))
  3586.          (if fin-diffs-also
  3587.          (ediff-clear-diff-vector 
  3588.           (ediff-get-fine-diff-vector-from-vec elt)))
  3589.          ))
  3590.       vec)
  3591.   ;; allow them to be garbage collected
  3592.   (setq vec nil))
  3593.       
  3594. (defun ediff-operate-on-flags (action)
  3595.   "Re/unhighlights buffers A and B with all flags from all Ediff sessions.
  3596. This is usually needed only when a
  3597. buffer is involved in multiple Ediff sessions."
  3598.   (let* ((A-sessions (emerge-eval-in-buffer
  3599.               ediff-A-buffer
  3600.               ediff-this-buffer-control-sessions))
  3601.      (B-sessions (emerge-eval-in-buffer
  3602.               ediff-B-buffer
  3603.               ediff-this-buffer-control-sessions))
  3604.      (sessions (ediff-union A-sessions B-sessions))
  3605.      (flag (if (eq action 'remove) 'unselect-only 'select-only)))
  3606.      
  3607.     (mapcar (function (lambda (buf)
  3608.             (if (ediff-buffer-live-p buf)
  3609.                 (emerge-eval-in-buffer
  3610.                  buf
  3611.                  (or (if (eq action 'insert)
  3612.                  (memq ediff-highlighting-style '(ascii off))
  3613.                  (not (eq ediff-highlighting-style 'ascii)))
  3614.                  (ediff-unselect-and-select-difference
  3615.                   ediff-current-difference 
  3616.                   flag 'no-recenter))
  3617.                  ))))
  3618.         sessions)))
  3619.  
  3620.  
  3621.  
  3622. ;;; Refinement of current diff        
  3623. ;; Split region along word boundaries. Each word will be on its own line.
  3624. ;; Output to buffer out-buffer.
  3625. (defun ediff-wordify (beg end in-buffer out-buffer)
  3626.   (let (sv-point string)
  3627.     (save-excursion
  3628.      (set-buffer in-buffer)
  3629.      (setq string (buffer-substring beg end))
  3630.  
  3631.      (set-buffer out-buffer)
  3632.      (erase-buffer)
  3633.      (insert string)
  3634.      (goto-char (point-min))
  3635.      (skip-chars-forward ediff-whitespace)
  3636.      (delete-region (point-min) (point))
  3637.      
  3638.      (while (or (> (skip-chars-forward ediff-word-1) 0)
  3639.         (> (skip-chars-forward ediff-word-2) 0))
  3640.        
  3641.        (setq sv-point (point))
  3642.        (skip-chars-forward ediff-whitespace)
  3643.        (delete-region sv-point (point))
  3644.        (insert "\n"))))) 
  3645.        
  3646.  
  3647. ;; `n' is the diff region to work on. 
  3648. ;; if `flag' is 'noforce then make fine-diffs only if this region's fine
  3649. ;; diffs have not been computed before.
  3650. ;; if `flag' is 'skip then don't compute fine diffs for this region.
  3651. (defun ediff-make-fine-diffs (&optional n flag)       
  3652.   (interactive)
  3653.   (if (not window-system)
  3654.       (error "Non-window system."))
  3655.   (or n  (setq n ediff-current-difference))
  3656.   
  3657.   (if (< ediff-number-of-differences 1)
  3658.       (error "No differences found."))
  3659.   
  3660.   (let ((file-A ediff-temp-file-A)
  3661.     (file-B ediff-temp-file-B))
  3662.     
  3663.     (cond ((and (eq flag 'noforce) (ediff-get-fine-diff-vector n))
  3664.        nil)
  3665.       ((eq flag 'skip)
  3666.        (or (ediff-get-fine-diff-vector n)
  3667.            (eq ediff-auto-refine 'off)
  3668.            (message "Region %d is larger than auto-refine limit. Hit %S to force-refine."
  3669.             (1+ n)
  3670.             (substitute-command-keys "\\[ediff-make-fine-diffs]")
  3671.             )))
  3672.       (t
  3673.        ;; delete old fine diffs
  3674.        (ediff-clear-diff-vector (ediff-get-fine-diff-vector n))
  3675.        ;; recompute fine diffs
  3676.        (setq ediff-tmp-buffer (get-buffer-create "*ediff-tmp*"))
  3677.       
  3678.        (funcall ediff-wordify-function
  3679.             (ediff-get-diff-posn 'A 'beg n)
  3680.             (ediff-get-diff-posn 'A 'end n)
  3681.             ediff-A-buffer
  3682.             ediff-tmp-buffer)
  3683.        (emerge-eval-in-buffer
  3684.         ediff-tmp-buffer
  3685.         (setq file-A (ediff-make-temp-file ".fine-diffs-A" file-A)))
  3686.     
  3687.        (funcall ediff-wordify-function
  3688.             (ediff-get-diff-posn 'B 'beg n)
  3689.             (ediff-get-diff-posn 'B 'end n)
  3690.             ediff-B-buffer
  3691.             ediff-tmp-buffer)
  3692.        (emerge-eval-in-buffer
  3693.         ediff-tmp-buffer
  3694.         (setq file-B (ediff-make-temp-file ".fine-diffs-B" file-B)))
  3695.    
  3696.        ;; save temp file names.
  3697.        (setq ediff-temp-file-A file-A
  3698.          ediff-temp-file-B file-B)
  3699.        
  3700.        ;; set the new vector of fine diffs, if none exists
  3701.        (ediff-set-fine-diff-vector
  3702.          n
  3703.          (ediff-setup-diff-regions file-A file-B 'use-old-diff-buf n
  3704.                        ediff-fine-diff-program
  3705.                        ediff-fine-diff-options
  3706.                        ediff-fine-diff-ok-lines-regexp))
  3707.        (if (eq (length (ediff-get-fine-diff-vector n)) 0)
  3708.            (message "No differences found in region %d, except for white space and line breaks."
  3709.             (1+ n))))
  3710.       ) ;; end cond
  3711.     (ediff-set-fine-diff-properties n)
  3712.     ))
  3713.     
  3714.     
  3715. (defun ediff-set-fine-diff-properties (n &optional default)
  3716.   (let ((fine-diff-vector  (ediff-get-fine-diff-vector n))
  3717.     (face-A (if default 'default (face-name ediff-fine-diff-face-A)))
  3718.     (face-B (if default 'default (face-name ediff-fine-diff-face-B)))
  3719.     (priority-A (if default
  3720.             0
  3721.               (1+ (ediff-overlay-get ediff-current-diff-overlay-A
  3722.                          'priority))))
  3723.     (priority-B (if default
  3724.             0
  3725.               (1+ (ediff-overlay-get ediff-current-diff-overlay-B
  3726.                          'priority)))))
  3727.     (mapcar
  3728.      (function (lambda (vec)
  3729.          (ediff-overlay-put 
  3730.           (ediff-get-diff-overlay-from-vector vec 'A)
  3731.           'face face-A)
  3732.          (ediff-overlay-put
  3733.           (ediff-get-diff-overlay-from-vector vec 'A)
  3734.           'priority priority-A)
  3735.          
  3736.          (ediff-overlay-put
  3737.           (ediff-get-diff-overlay-from-vector vec 'B)
  3738.           'face face-B)
  3739.          (ediff-overlay-put
  3740.           (ediff-get-diff-overlay-from-vector vec 'B)
  3741.           'priority priority-B)
  3742.          ))
  3743.      fine-diff-vector)
  3744.     ))
  3745.     
  3746. (defun ediff-convert-diffs-to-overlays-refine (A-buffer B-buffer
  3747.                         diff-list refine-region)
  3748.   (let* ((current-diff -1)
  3749.      (reg-A-start (ediff-get-diff-posn 'A 'beg refine-region))
  3750.      (reg-B-start (ediff-get-diff-posn 'B 'beg refine-region))
  3751.      diff-overlay-list list-element
  3752.      a-begin a-end b-begin b-end
  3753.      a-overlay b-overlay)
  3754.  
  3755.     (emerge-eval-in-buffer A-buffer (goto-char reg-A-start))
  3756.     (emerge-eval-in-buffer B-buffer (goto-char reg-B-start))
  3757.      
  3758.     (while diff-list
  3759.       (setq current-diff (1+ current-diff)
  3760.         list-element (car diff-list)
  3761.         a-begin      (aref list-element 0)
  3762.         a-end      (aref list-element 1)
  3763.         b-begin      (aref list-element 2)
  3764.         b-end      (aref list-element 3))
  3765.         
  3766.       ;; place overlays at the appropriate places in the buffers
  3767.       (setq a-overlay (ediff-make-overlay 
  3768.                (ediff-goto-word (1+ a-begin) A-buffer)
  3769.                (ediff-goto-word a-end A-buffer 'end)
  3770.                A-buffer))
  3771.              
  3772.     (setq b-overlay (ediff-make-overlay 
  3773.              (ediff-goto-word (1+ b-begin) B-buffer)
  3774.              (ediff-goto-word b-end B-buffer 'end)
  3775.              B-buffer))
  3776.              
  3777.       ;; record all overlays for this difference
  3778.       (setq diff-overlay-list (nconc diff-overlay-list
  3779.                      (list (vector a-overlay b-overlay)))
  3780.         diff-list (cdr diff-list))
  3781.       ) ;; while
  3782.     ;; convert the list of difference information into a vector for
  3783.     ;; fast access
  3784.     (apply 'vector diff-overlay-list)))
  3785.  
  3786. ;; goto word #n starting at current position in buffer `buf'
  3787. ;; For ediff, a word is either a string of a-z,A-Z, incl `-' and `_';
  3788. ;; or a string of other non-blanks. A blank is a \n\t\j
  3789. ;; If `flag' is non-nil, goto the end of the n-th word.
  3790. (defun ediff-goto-word (n buf &optional flag)
  3791.   (emerge-eval-in-buffer
  3792.    buf
  3793.    (skip-chars-forward ediff-whitespace)
  3794.    (while (> n 1)
  3795.      (or (> (skip-chars-forward ediff-word-1) 0)
  3796.      (> (skip-chars-forward ediff-word-2) 0))
  3797.      (skip-chars-forward ediff-whitespace)
  3798.      (setq n (1- n)))
  3799.    ;(if flag
  3800.    (if (and flag (> n 0))
  3801.        (or (> (skip-chars-forward ediff-word-1) 0)
  3802.        (> (skip-chars-forward ediff-word-2) 0)))
  3803.    (point)))
  3804.  
  3805.   
  3806.        
  3807.        
  3808.  
  3809. ;;; Misc
  3810.        
  3811. (defun ediff-union (list1 list2)
  3812.   "Combine LIST1 and LIST2 using a set-union operation.
  3813. The result list contains all items that appear in either LIST1 or LIST2.
  3814. This is a non-destructive function; it makes a copy of the data if necessary
  3815. to avoid corrupting the original LIST1 and LIST2.
  3816. This is a slightly simplified version from `cl-seq.el'.  Added here to
  3817. avoid loading cl-*."
  3818.   (cond ((null list1) list2) ((null list2) list1)
  3819.     ((equal list1 list2) list1)
  3820.     (t
  3821.      (or (>= (length list1) (length list2))
  3822.          (setq list1 (prog1 list2 (setq list2 list1))))
  3823.      (while list2
  3824.        (or (memq (car list2) list1)
  3825.            (setq list1 (cons (car list2) list1)))
  3826.        (setq list2 (cdr list2)))
  3827.      list1)))
  3828.      
  3829.  
  3830. ;(defun ediff-debug ()
  3831. ;  (interactive)
  3832. ;  (with-output-to-temp-buffer "*ediff-debug*"
  3833. ;    (princ 
  3834. ;     (format "Ctl buffer: %S\n\nediff-difference-vector:\n"
  3835. ;         ediff-control-buffer))
  3836. ;    (mapcar (function
  3837. ;         (lambda (overl-vec)
  3838. ;           (princ (format "Diff %d:  %S %S %S\n\t %S %S %S\n" 
  3839. ;                  (1+ (ediff-overlay-get (aref overl-vec 0)
  3840. ;                             'ediff-diff-num))
  3841. ;                  (ediff-overlay-get (aref overl-vec 0)
  3842. ;                         'ediff-control-buffer) 
  3843. ;                  (ediff-overlay-get (aref overl-vec 0)
  3844. ;                         'insert-in-front-hooks)
  3845. ;                  (aref overl-vec 0)
  3846. ;                  (ediff-overlay-get (aref overl-vec 1)
  3847. ;                         'ediff-control-buffer) 
  3848. ;                  (ediff-overlay-get (aref overl-vec 0)
  3849. ;                         'insert-in-front-hooks)
  3850. ;                  (aref overl-vec 1)
  3851. ;                  ))))
  3852. ;        ediff-difference-vector)
  3853. ;    (princ "\nediff-disturbed-overlays:\n")
  3854. ;    (mapcar (function
  3855. ;         (lambda (overl)
  3856. ;           (princ (format "%S  %S\n"
  3857. ;                  (ediff-overlay-get overl 'ediff-control-buffer)
  3858. ;                  overl
  3859. ;                  ))))
  3860. ;        ediff-disturbed-overlays)))
  3861.  
  3862.   
  3863. (run-hooks 'ediff-load-hooks)
  3864.   
  3865.  
  3866. (provide 'ediff)
  3867.  
  3868. ;;; ediff.el ends here
  3869.